github.com/vcilabs/webrpc@v0.5.2-0.20201116131534-162e27b1b33b/_examples/hello-webrpc-with-goschema-ts/server/hello_api.gen.go (about)

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