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  )