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  )