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