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