github.com/vcilabs/webrpc@v0.5.2-0.20201116131534-162e27b1b33b/_examples/golang-nodejs/server/server.gen.go (about) 1 // example v0.0.1 07d79ad7e0e7bc2320ac29fdd065307ce932cf47 2 // -- 3 // This file has been generated by https://github.com/webrpc/webrpc using gen/golang 4 // Do not edit by hand. Update your webrpc schema and re-generate. 5 package main 6 7 import ( 8 "bytes" 9 "context" 10 "encoding/json" 11 "fmt" 12 "io/ioutil" 13 "net/http" 14 "strings" 15 "time" 16 ) 17 18 // WebRPC description and code-gen version 19 func WebRPCVersion() string { 20 return "v1" 21 } 22 23 // Schema version of your RIDL schema 24 func WebRPCSchemaVersion() string { 25 return " v0.0.1" 26 } 27 28 // Schema hash generated from your RIDL schema 29 func WebRPCSchemaHash() string { 30 return "07d79ad7e0e7bc2320ac29fdd065307ce932cf47" 31 } 32 33 // 34 // Types 35 // 36 37 type Kind uint32 38 39 const ( 40 Kind_USER Kind = 1 41 Kind_ADMIN Kind = 2 42 ) 43 44 var Kind_name = map[uint32]string{ 45 1: "USER", 46 2: "ADMIN", 47 } 48 49 var Kind_value = map[string]uint32{ 50 "USER": 1, 51 "ADMIN": 2, 52 } 53 54 func (x Kind) String() string { 55 return Kind_name[uint32(x)] 56 } 57 58 func (x Kind) MarshalJSON() ([]byte, error) { 59 buf := bytes.NewBufferString(`"`) 60 buf.WriteString(Kind_name[uint32(x)]) 61 buf.WriteString(`"`) 62 return buf.Bytes(), nil 63 } 64 65 func (x *Kind) UnmarshalJSON(b []byte) error { 66 var j string 67 err := json.Unmarshal(b, &j) 68 if err != nil { 69 return err 70 } 71 *x = Kind(Kind_value[j]) 72 return nil 73 } 74 75 type Empty struct { 76 } 77 78 type GetUserRequest struct { 79 UserID uint64 `json:"userID"` 80 } 81 82 type User struct { 83 ID uint64 `json:"id" db:"id"` 84 Username string `json:"USERNAME" db:"username"` 85 CreatedAt *time.Time `json:"created_at,omitempty" db:"created_at"` 86 } 87 88 type RandomStuff struct { 89 Meta map[string]interface{} `json:"meta"` 90 MetaNestedExample map[string]map[string]uint32 `json:"metaNestedExample"` 91 NamesList []string `json:"namesList"` 92 NumsList []int64 `json:"numsList"` 93 DoubleArray [][]string `json:"doubleArray"` 94 ListOfMaps []map[string]uint32 `json:"listOfMaps"` 95 ListOfUsers []*User `json:"listOfUsers"` 96 MapOfUsers map[string]*User `json:"mapOfUsers"` 97 User *User `json:"user"` 98 } 99 100 type ExampleService interface { 101 Ping(ctx context.Context) (bool, error) 102 GetUser(ctx context.Context, req *GetUserRequest) (*User, error) 103 } 104 105 var WebRPCServices = map[string][]string{ 106 "ExampleService": { 107 "Ping", 108 "GetUser", 109 }, 110 } 111 112 // 113 // Server 114 // 115 116 type WebRPCServer interface { 117 http.Handler 118 } 119 120 type exampleServiceServer struct { 121 ExampleService 122 } 123 124 func NewExampleServiceServer(svc ExampleService) WebRPCServer { 125 return &exampleServiceServer{ 126 ExampleService: svc, 127 } 128 } 129 130 func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { 131 ctx := r.Context() 132 ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) 133 ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) 134 ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") 135 136 if r.Method != "POST" { 137 err := Errorf(ErrBadRoute, "unsupported method %q (only POST is allowed)", r.Method) 138 RespondWithError(w, err) 139 return 140 } 141 142 switch r.URL.Path { 143 case "/rpc/ExampleService/Ping": 144 s.servePing(ctx, w, r) 145 return 146 case "/rpc/ExampleService/GetUser": 147 s.serveGetUser(ctx, w, r) 148 return 149 default: 150 err := Errorf(ErrBadRoute, "no handler for path %q", r.URL.Path) 151 RespondWithError(w, err) 152 return 153 } 154 } 155 156 func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWriter, r *http.Request) { 157 header := r.Header.Get("Content-Type") 158 i := strings.Index(header, ";") 159 if i == -1 { 160 i = len(header) 161 } 162 163 switch strings.TrimSpace(strings.ToLower(header[:i])) { 164 case "application/json": 165 s.servePingJSON(ctx, w, r) 166 default: 167 err := Errorf(ErrBadRoute, "unexpected Content-Type: %q", r.Header.Get("Content-Type")) 168 RespondWithError(w, err) 169 } 170 } 171 172 func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { 173 var err error 174 ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") 175 176 // Call service method 177 var ret0 bool 178 func() { 179 defer func() { 180 // In case of a panic, serve a 500 error and then panic. 181 if rr := recover(); rr != nil { 182 RespondWithError(w, ErrorInternal("internal service panic")) 183 panic(rr) 184 } 185 }() 186 ret0, err = s.ExampleService.Ping(ctx) 187 }() 188 respContent := struct { 189 Ret0 bool `json:"status"` 190 }{ret0} 191 192 if err != nil { 193 RespondWithError(w, err) 194 return 195 } 196 respBody, err := json.Marshal(respContent) 197 if err != nil { 198 err = WrapError(ErrInternal, err, "failed to marshal json response") 199 RespondWithError(w, err) 200 return 201 } 202 203 w.Header().Set("Content-Type", "application/json") 204 w.WriteHeader(http.StatusOK) 205 w.Write(respBody) 206 } 207 208 func (s *exampleServiceServer) serveGetUser(ctx context.Context, w http.ResponseWriter, r *http.Request) { 209 header := r.Header.Get("Content-Type") 210 i := strings.Index(header, ";") 211 if i == -1 { 212 i = len(header) 213 } 214 215 switch strings.TrimSpace(strings.ToLower(header[:i])) { 216 case "application/json": 217 s.serveGetUserJSON(ctx, w, r) 218 default: 219 err := Errorf(ErrBadRoute, "unexpected Content-Type: %q", r.Header.Get("Content-Type")) 220 RespondWithError(w, err) 221 } 222 } 223 224 func (s *exampleServiceServer) serveGetUserJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { 225 var err error 226 ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") 227 reqContent := struct { 228 Arg0 *GetUserRequest `json:"req"` 229 }{} 230 231 reqBody, err := ioutil.ReadAll(r.Body) 232 if err != nil { 233 err = WrapError(ErrInternal, err, "failed to read request data") 234 RespondWithError(w, err) 235 return 236 } 237 defer r.Body.Close() 238 239 err = json.Unmarshal(reqBody, &reqContent) 240 if err != nil { 241 err = WrapError(ErrInvalidArgument, err, "failed to unmarshal request data") 242 RespondWithError(w, err) 243 return 244 } 245 246 // Call service method 247 var ret0 *User 248 func() { 249 defer func() { 250 // In case of a panic, serve a 500 error and then panic. 251 if rr := recover(); rr != nil { 252 RespondWithError(w, ErrorInternal("internal service panic")) 253 panic(rr) 254 } 255 }() 256 ret0, err = s.ExampleService.GetUser(ctx, reqContent.Arg0) 257 }() 258 respContent := struct { 259 Ret0 *User `json:"user"` 260 }{ret0} 261 262 if err != nil { 263 RespondWithError(w, err) 264 return 265 } 266 respBody, err := json.Marshal(respContent) 267 if err != nil { 268 err = WrapError(ErrInternal, err, "failed to marshal json response") 269 RespondWithError(w, err) 270 return 271 } 272 273 w.Header().Set("Content-Type", "application/json") 274 w.WriteHeader(http.StatusOK) 275 w.Write(respBody) 276 } 277 278 func RespondWithError(w http.ResponseWriter, err error) { 279 rpcErr, ok := err.(Error) 280 if !ok { 281 rpcErr = WrapError(ErrInternal, err, "webrpc error") 282 } 283 284 statusCode := HTTPStatusFromErrorCode(rpcErr.Code()) 285 286 w.Header().Set("Content-Type", "application/json") 287 w.WriteHeader(statusCode) 288 289 respBody, _ := json.Marshal(rpcErr.Payload()) 290 w.Write(respBody) 291 } 292 293 // 294 // Helpers 295 // 296 297 type ErrorPayload struct { 298 Status int `json:"status"` 299 Code string `json:"code"` 300 Cause string `json:"cause,omitempty"` 301 Msg string `json:"msg"` 302 Error string `json:"error"` 303 } 304 305 type Error interface { 306 // Code is of the valid error codes 307 Code() ErrorCode 308 309 // Msg returns a human-readable, unstructured messages describing the error 310 Msg() string 311 312 // Cause is reason for the error 313 Cause() error 314 315 // Error returns a string of the form "webrpc error <Code>: <Msg>" 316 Error() string 317 318 // Error response payload 319 Payload() ErrorPayload 320 } 321 322 func Errorf(code ErrorCode, msgf string, args ...interface{}) Error { 323 msg := fmt.Sprintf(msgf, args...) 324 if IsValidErrorCode(code) { 325 return &rpcErr{code: code, msg: msg} 326 } 327 return &rpcErr{code: ErrInternal, msg: "invalid error type " + string(code)} 328 } 329 330 func WrapError(code ErrorCode, cause error, format string, args ...interface{}) Error { 331 msg := fmt.Sprintf(format, args...) 332 if IsValidErrorCode(code) { 333 return &rpcErr{code: code, msg: msg, cause: cause} 334 } 335 return &rpcErr{code: ErrInternal, msg: "invalid error type " + string(code), cause: cause} 336 } 337 338 func ErrorNotFound(format string, args ...interface{}) Error { 339 return Errorf(ErrNotFound, format, args...) 340 } 341 342 func ErrorInvalidArgument(argument string, validationMsg string) Error { 343 return Errorf(ErrInvalidArgument, argument+" "+validationMsg) 344 } 345 346 func ErrorRequiredArgument(argument string) Error { 347 return ErrorInvalidArgument(argument, "is required") 348 } 349 350 func ErrorInternal(format string, args ...interface{}) Error { 351 return Errorf(ErrInternal, format, args...) 352 } 353 354 type ErrorCode string 355 356 const ( 357 // Canceled indicates the operation was cancelled (typically by the caller). 358 ErrCanceled ErrorCode = "canceled" 359 360 // Unknown error. For example when handling errors raised by APIs that do not 361 // return enough error information. 362 ErrUnknown ErrorCode = "unknown" 363 364 // InvalidArgument indicates client specified an invalid argument. It 365 // indicates arguments that are problematic regardless of the state of the 366 // system (i.e. a malformed file name, required argument, number out of range, 367 // etc.). 368 ErrInvalidArgument ErrorCode = "invalid argument" 369 370 // DeadlineExceeded means operation expired before completion. For operations 371 // that change the state of the system, this error may be returned even if the 372 // operation has completed successfully (timeout). 373 ErrDeadlineExceeded ErrorCode = "deadline exceeded" 374 375 // NotFound means some requested entity was not found. 376 ErrNotFound ErrorCode = "not found" 377 378 // BadRoute means that the requested URL path wasn't routable to a webrpc 379 // service and method. This is returned by the generated server, and usually 380 // shouldn't be returned by applications. Instead, applications should use 381 // NotFound or Unimplemented. 382 ErrBadRoute ErrorCode = "bad route" 383 384 // AlreadyExists means an attempt to create an entity failed because one 385 // already exists. 386 ErrAlreadyExists ErrorCode = "already exists" 387 388 // PermissionDenied indicates the caller does not have permission to execute 389 // the specified operation. It must not be used if the caller cannot be 390 // identified (Unauthenticated). 391 ErrPermissionDenied ErrorCode = "permission denied" 392 393 // Unauthenticated indicates the request does not have valid authentication 394 // credentials for the operation. 395 ErrUnauthenticated ErrorCode = "unauthenticated" 396 397 // ResourceExhausted indicates some resource has been exhausted, perhaps a 398 // per-user quota, or perhaps the entire file system is out of space. 399 ErrResourceExhausted ErrorCode = "resource exhausted" 400 401 // FailedPrecondition indicates operation was rejected because the system is 402 // not in a state required for the operation's execution. For example, doing 403 // an rmdir operation on a directory that is non-empty, or on a non-directory 404 // object, or when having conflicting read-modify-write on the same resource. 405 ErrFailedPrecondition ErrorCode = "failed precondition" 406 407 // Aborted indicates the operation was aborted, typically due to a concurrency 408 // issue like sequencer check failures, transaction aborts, etc. 409 ErrAborted ErrorCode = "aborted" 410 411 // OutOfRange means operation was attempted past the valid range. For example, 412 // seeking or reading past end of a paginated collection. 413 // 414 // Unlike InvalidArgument, this error indicates a problem that may be fixed if 415 // the system state changes (i.e. adding more items to the collection). 416 // 417 // There is a fair bit of overlap between FailedPrecondition and OutOfRange. 418 // We recommend using OutOfRange (the more specific error) when it applies so 419 // that callers who are iterating through a space can easily look for an 420 // OutOfRange error to detect when they are done. 421 ErrOutOfRange ErrorCode = "out of range" 422 423 // Unimplemented indicates operation is not implemented or not 424 // supported/enabled in this service. 425 ErrUnimplemented ErrorCode = "unimplemented" 426 427 // Internal errors. When some invariants expected by the underlying system 428 // have been broken. In other words, something bad happened in the library or 429 // backend service. Do not confuse with HTTP Internal Server Error; an 430 // Internal error could also happen on the client code, i.e. when parsing a 431 // server response. 432 ErrInternal ErrorCode = "internal" 433 434 // Unavailable indicates the service is currently unavailable. This is a most 435 // likely a transient condition and may be corrected by retrying with a 436 // backoff. 437 ErrUnavailable ErrorCode = "unavailable" 438 439 // DataLoss indicates unrecoverable data loss or corruption. 440 ErrDataLoss ErrorCode = "data loss" 441 442 // ErrNone is the zero-value, is considered an empty error and should not be 443 // used. 444 ErrNone ErrorCode = "" 445 ) 446 447 func HTTPStatusFromErrorCode(code ErrorCode) int { 448 switch code { 449 case ErrCanceled: 450 return 408 // RequestTimeout 451 case ErrUnknown: 452 return 500 // Internal Server Error 453 case ErrInvalidArgument: 454 return 400 // BadRequest 455 case ErrDeadlineExceeded: 456 return 408 // RequestTimeout 457 case ErrNotFound: 458 return 404 // Not Found 459 case ErrBadRoute: 460 return 404 // Not Found 461 case ErrAlreadyExists: 462 return 409 // Conflict 463 case ErrPermissionDenied: 464 return 403 // Forbidden 465 case ErrUnauthenticated: 466 return 401 // Unauthorized 467 case ErrResourceExhausted: 468 return 403 // Forbidden 469 case ErrFailedPrecondition: 470 return 412 // Precondition Failed 471 case ErrAborted: 472 return 409 // Conflict 473 case ErrOutOfRange: 474 return 400 // Bad Request 475 case ErrUnimplemented: 476 return 501 // Not Implemented 477 case ErrInternal: 478 return 500 // Internal Server Error 479 case ErrUnavailable: 480 return 503 // Service Unavailable 481 case ErrDataLoss: 482 return 500 // Internal Server Error 483 case ErrNone: 484 return 200 // OK 485 default: 486 return 0 // Invalid! 487 } 488 } 489 490 func IsErrorCode(err error, code ErrorCode) bool { 491 if rpcErr, ok := err.(Error); ok { 492 if rpcErr.Code() == code { 493 return true 494 } 495 } 496 return false 497 } 498 499 func IsValidErrorCode(code ErrorCode) bool { 500 return HTTPStatusFromErrorCode(code) != 0 501 } 502 503 type rpcErr struct { 504 code ErrorCode 505 msg string 506 cause error 507 } 508 509 func (e *rpcErr) Code() ErrorCode { 510 return e.code 511 } 512 513 func (e *rpcErr) Msg() string { 514 return e.msg 515 } 516 517 func (e *rpcErr) Cause() error { 518 return e.cause 519 } 520 521 func (e *rpcErr) Error() string { 522 if e.cause != nil && e.cause.Error() != "" { 523 if e.msg != "" { 524 return fmt.Sprintf("webrpc %s error: %s -- %s", e.code, e.cause.Error(), e.msg) 525 } else { 526 return fmt.Sprintf("webrpc %s error: %s", e.code, e.cause.Error()) 527 } 528 } else { 529 return fmt.Sprintf("webrpc %s error: %s", e.code, e.msg) 530 } 531 } 532 533 func (e *rpcErr) Payload() ErrorPayload { 534 statusCode := HTTPStatusFromErrorCode(e.Code()) 535 errPayload := ErrorPayload{ 536 Status: statusCode, 537 Code: string(e.Code()), 538 Msg: e.Msg(), 539 Error: e.Error(), 540 } 541 if e.Cause() != nil { 542 errPayload.Cause = e.Cause().Error() 543 } 544 return errPayload 545 } 546 547 type contextKey struct { 548 name string 549 } 550 551 func (k *contextKey) String() string { 552 return "webrpc context value " + k.name 553 } 554 555 var ( 556 // For Client 557 HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} 558 559 // For Server 560 HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} 561 562 HTTPRequestCtxKey = &contextKey{"HTTPRequest"} 563 564 ServiceNameCtxKey = &contextKey{"ServiceName"} 565 566 MethodNameCtxKey = &contextKey{"MethodName"} 567 )