2022-12-18 05:01:50 +00:00
// Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT.
// source: lure.proto
package api
import context "context"
import fmt "fmt"
import http "net/http"
import io "io"
import json "encoding/json"
import strconv "strconv"
import strings "strings"
import protojson "google.golang.org/protobuf/encoding/protojson"
import proto "google.golang.org/protobuf/proto"
import twirp "github.com/twitchtv/twirp"
import ctxsetters "github.com/twitchtv/twirp/ctxsetters"
import bytes "bytes"
import errors "errors"
import path "path"
import url "net/url"
// Version compatibility assertion.
// If the constant is not defined in the package, that likely means
// the package needs to be updated to work with this generated code.
// See https://twitchtv.github.io/twirp/docs/version_matrix.html
const _ = twirp . TwirpPackageMinVersion_8_1_0
// =============
// API Interface
// =============
// Web is the LURE Web service
type API interface {
// CreateComment creates a new comment on the given package
CreateComment ( context . Context , * CreateCommentRequest ) ( * CreateCommentResponse , error )
// EditComment edits an existing comment
EditComment ( context . Context , * EditCommentRequest ) ( * EmptyResponse , error )
// GetComments returns the comments on a particular package
GetComments ( context . Context , * GetCommentsRequest ) ( * GetCommentsResponse , error )
// Search searches through LURE packages in the database
Search ( context . Context , * SearchRequest ) ( * SearchResponse , error )
2022-12-18 07:10:34 +00:00
// GetPkg gets a single LURE package from the database
GetPkg ( context . Context , * GetPackageRequest ) ( * Package , error )
2022-12-18 05:01:50 +00:00
}
// ===================
// API Protobuf Client
// ===================
type aPIProtobufClient struct {
client HTTPClient
2022-12-18 07:10:34 +00:00
urls [ 5 ] string
2022-12-18 05:01:50 +00:00
interceptor twirp . Interceptor
opts twirp . ClientOptions
}
// NewAPIProtobufClient creates a Protobuf client that implements the API interface.
// It communicates using Protobuf and can be configured with a custom HTTPClient.
func NewAPIProtobufClient ( baseURL string , client HTTPClient , opts ... twirp . ClientOption ) API {
if c , ok := client . ( * http . Client ) ; ok {
client = withoutRedirects ( c )
}
clientOpts := twirp . ClientOptions { }
for _ , o := range opts {
o ( & clientOpts )
}
// Using ReadOpt allows backwards and forwards compatibility with new options in the future
literalURLs := false
_ = clientOpts . ReadOpt ( "literalURLs" , & literalURLs )
var pathPrefix string
if ok := clientOpts . ReadOpt ( "pathPrefix" , & pathPrefix ) ; ! ok {
pathPrefix = "/twirp" // default prefix
}
// Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method>
serviceURL := sanitizeBaseURL ( baseURL )
serviceURL += baseServicePath ( pathPrefix , "lure" , "API" )
2022-12-18 07:10:34 +00:00
urls := [ 5 ] string {
2022-12-18 05:01:50 +00:00
serviceURL + "CreateComment" ,
serviceURL + "EditComment" ,
serviceURL + "GetComments" ,
serviceURL + "Search" ,
2022-12-18 07:10:34 +00:00
serviceURL + "GetPkg" ,
2022-12-18 05:01:50 +00:00
}
return & aPIProtobufClient {
client : client ,
urls : urls ,
interceptor : twirp . ChainInterceptors ( clientOpts . Interceptors ... ) ,
opts : clientOpts ,
}
}
func ( c * aPIProtobufClient ) CreateComment ( ctx context . Context , in * CreateCommentRequest ) ( * CreateCommentResponse , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "CreateComment" )
caller := c . callCreateComment
if c . interceptor != nil {
caller = func ( ctx context . Context , req * CreateCommentRequest ) ( * CreateCommentResponse , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * CreateCommentRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*CreateCommentRequest) when calling interceptor" )
}
return c . callCreateComment ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * CreateCommentResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*CreateCommentResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIProtobufClient ) callCreateComment ( ctx context . Context , in * CreateCommentRequest ) ( * CreateCommentResponse , error ) {
out := new ( CreateCommentResponse )
ctx , err := doProtobufRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 0 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
func ( c * aPIProtobufClient ) EditComment ( ctx context . Context , in * EditCommentRequest ) ( * EmptyResponse , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "EditComment" )
caller := c . callEditComment
if c . interceptor != nil {
caller = func ( ctx context . Context , req * EditCommentRequest ) ( * EmptyResponse , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * EditCommentRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*EditCommentRequest) when calling interceptor" )
}
return c . callEditComment ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * EmptyResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*EmptyResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIProtobufClient ) callEditComment ( ctx context . Context , in * EditCommentRequest ) ( * EmptyResponse , error ) {
out := new ( EmptyResponse )
ctx , err := doProtobufRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 1 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
func ( c * aPIProtobufClient ) GetComments ( ctx context . Context , in * GetCommentsRequest ) ( * GetCommentsResponse , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "GetComments" )
caller := c . callGetComments
if c . interceptor != nil {
caller = func ( ctx context . Context , req * GetCommentsRequest ) ( * GetCommentsResponse , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * GetCommentsRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*GetCommentsRequest) when calling interceptor" )
}
return c . callGetComments ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * GetCommentsResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*GetCommentsResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIProtobufClient ) callGetComments ( ctx context . Context , in * GetCommentsRequest ) ( * GetCommentsResponse , error ) {
out := new ( GetCommentsResponse )
ctx , err := doProtobufRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 2 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
func ( c * aPIProtobufClient ) Search ( ctx context . Context , in * SearchRequest ) ( * SearchResponse , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "Search" )
caller := c . callSearch
if c . interceptor != nil {
caller = func ( ctx context . Context , req * SearchRequest ) ( * SearchResponse , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * SearchRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*SearchRequest) when calling interceptor" )
}
return c . callSearch ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * SearchResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*SearchResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIProtobufClient ) callSearch ( ctx context . Context , in * SearchRequest ) ( * SearchResponse , error ) {
out := new ( SearchResponse )
ctx , err := doProtobufRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 3 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
2022-12-18 07:10:34 +00:00
func ( c * aPIProtobufClient ) GetPkg ( ctx context . Context , in * GetPackageRequest ) ( * Package , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "GetPkg" )
caller := c . callGetPkg
if c . interceptor != nil {
caller = func ( ctx context . Context , req * GetPackageRequest ) ( * Package , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * GetPackageRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*GetPackageRequest) when calling interceptor" )
}
return c . callGetPkg ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * Package )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*Package) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIProtobufClient ) callGetPkg ( ctx context . Context , in * GetPackageRequest ) ( * Package , error ) {
out := new ( Package )
ctx , err := doProtobufRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 4 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
2022-12-18 05:01:50 +00:00
// ===============
// API JSON Client
// ===============
type aPIJSONClient struct {
client HTTPClient
2022-12-18 07:10:34 +00:00
urls [ 5 ] string
2022-12-18 05:01:50 +00:00
interceptor twirp . Interceptor
opts twirp . ClientOptions
}
// NewAPIJSONClient creates a JSON client that implements the API interface.
// It communicates using JSON and can be configured with a custom HTTPClient.
func NewAPIJSONClient ( baseURL string , client HTTPClient , opts ... twirp . ClientOption ) API {
if c , ok := client . ( * http . Client ) ; ok {
client = withoutRedirects ( c )
}
clientOpts := twirp . ClientOptions { }
for _ , o := range opts {
o ( & clientOpts )
}
// Using ReadOpt allows backwards and forwards compatibility with new options in the future
literalURLs := false
_ = clientOpts . ReadOpt ( "literalURLs" , & literalURLs )
var pathPrefix string
if ok := clientOpts . ReadOpt ( "pathPrefix" , & pathPrefix ) ; ! ok {
pathPrefix = "/twirp" // default prefix
}
// Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method>
serviceURL := sanitizeBaseURL ( baseURL )
serviceURL += baseServicePath ( pathPrefix , "lure" , "API" )
2022-12-18 07:10:34 +00:00
urls := [ 5 ] string {
2022-12-18 05:01:50 +00:00
serviceURL + "CreateComment" ,
serviceURL + "EditComment" ,
serviceURL + "GetComments" ,
serviceURL + "Search" ,
2022-12-18 07:10:34 +00:00
serviceURL + "GetPkg" ,
2022-12-18 05:01:50 +00:00
}
return & aPIJSONClient {
client : client ,
urls : urls ,
interceptor : twirp . ChainInterceptors ( clientOpts . Interceptors ... ) ,
opts : clientOpts ,
}
}
func ( c * aPIJSONClient ) CreateComment ( ctx context . Context , in * CreateCommentRequest ) ( * CreateCommentResponse , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "CreateComment" )
caller := c . callCreateComment
if c . interceptor != nil {
caller = func ( ctx context . Context , req * CreateCommentRequest ) ( * CreateCommentResponse , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * CreateCommentRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*CreateCommentRequest) when calling interceptor" )
}
return c . callCreateComment ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * CreateCommentResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*CreateCommentResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIJSONClient ) callCreateComment ( ctx context . Context , in * CreateCommentRequest ) ( * CreateCommentResponse , error ) {
out := new ( CreateCommentResponse )
ctx , err := doJSONRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 0 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
func ( c * aPIJSONClient ) EditComment ( ctx context . Context , in * EditCommentRequest ) ( * EmptyResponse , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "EditComment" )
caller := c . callEditComment
if c . interceptor != nil {
caller = func ( ctx context . Context , req * EditCommentRequest ) ( * EmptyResponse , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * EditCommentRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*EditCommentRequest) when calling interceptor" )
}
return c . callEditComment ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * EmptyResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*EmptyResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIJSONClient ) callEditComment ( ctx context . Context , in * EditCommentRequest ) ( * EmptyResponse , error ) {
out := new ( EmptyResponse )
ctx , err := doJSONRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 1 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
func ( c * aPIJSONClient ) GetComments ( ctx context . Context , in * GetCommentsRequest ) ( * GetCommentsResponse , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "GetComments" )
caller := c . callGetComments
if c . interceptor != nil {
caller = func ( ctx context . Context , req * GetCommentsRequest ) ( * GetCommentsResponse , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * GetCommentsRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*GetCommentsRequest) when calling interceptor" )
}
return c . callGetComments ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * GetCommentsResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*GetCommentsResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIJSONClient ) callGetComments ( ctx context . Context , in * GetCommentsRequest ) ( * GetCommentsResponse , error ) {
out := new ( GetCommentsResponse )
ctx , err := doJSONRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 2 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
func ( c * aPIJSONClient ) Search ( ctx context . Context , in * SearchRequest ) ( * SearchResponse , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "Search" )
caller := c . callSearch
if c . interceptor != nil {
caller = func ( ctx context . Context , req * SearchRequest ) ( * SearchResponse , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * SearchRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*SearchRequest) when calling interceptor" )
}
return c . callSearch ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * SearchResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*SearchResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIJSONClient ) callSearch ( ctx context . Context , in * SearchRequest ) ( * SearchResponse , error ) {
out := new ( SearchResponse )
ctx , err := doJSONRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 3 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
2022-12-18 07:10:34 +00:00
func ( c * aPIJSONClient ) GetPkg ( ctx context . Context , in * GetPackageRequest ) ( * Package , error ) {
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithMethodName ( ctx , "GetPkg" )
caller := c . callGetPkg
if c . interceptor != nil {
caller = func ( ctx context . Context , req * GetPackageRequest ) ( * Package , error ) {
resp , err := c . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * GetPackageRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*GetPackageRequest) when calling interceptor" )
}
return c . callGetPkg ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * Package )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*Package) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
return caller ( ctx , in )
}
func ( c * aPIJSONClient ) callGetPkg ( ctx context . Context , in * GetPackageRequest ) ( * Package , error ) {
out := new ( Package )
ctx , err := doJSONRequest ( ctx , c . client , c . opts . Hooks , c . urls [ 4 ] , in , out )
if err != nil {
twerr , ok := err . ( twirp . Error )
if ! ok {
twerr = twirp . InternalErrorWith ( err )
}
callClientError ( ctx , c . opts . Hooks , twerr )
return nil , err
}
callClientResponseReceived ( ctx , c . opts . Hooks )
return out , nil
}
2022-12-18 05:01:50 +00:00
// ==================
// API Server Handler
// ==================
type aPIServer struct {
API
interceptor twirp . Interceptor
hooks * twirp . ServerHooks
pathPrefix string // prefix for routing
jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response
jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names
}
// NewAPIServer builds a TwirpServer that can be used as an http.Handler to handle
// HTTP requests that are routed to the right method in the provided svc implementation.
// The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks).
func NewAPIServer ( svc API , opts ... interface { } ) TwirpServer {
serverOpts := newServerOpts ( opts )
// Using ReadOpt allows backwards and forwards compatibility with new options in the future
jsonSkipDefaults := false
_ = serverOpts . ReadOpt ( "jsonSkipDefaults" , & jsonSkipDefaults )
jsonCamelCase := false
_ = serverOpts . ReadOpt ( "jsonCamelCase" , & jsonCamelCase )
var pathPrefix string
if ok := serverOpts . ReadOpt ( "pathPrefix" , & pathPrefix ) ; ! ok {
pathPrefix = "/twirp" // default prefix
}
return & aPIServer {
API : svc ,
hooks : serverOpts . Hooks ,
interceptor : twirp . ChainInterceptors ( serverOpts . Interceptors ... ) ,
pathPrefix : pathPrefix ,
jsonSkipDefaults : jsonSkipDefaults ,
jsonCamelCase : jsonCamelCase ,
}
}
// writeError writes an HTTP response with a valid Twirp error format, and triggers hooks.
// If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err)
func ( s * aPIServer ) writeError ( ctx context . Context , resp http . ResponseWriter , err error ) {
writeError ( ctx , resp , err , s . hooks )
}
// handleRequestBodyError is used to handle error when the twirp server cannot read request
func ( s * aPIServer ) handleRequestBodyError ( ctx context . Context , resp http . ResponseWriter , msg string , err error ) {
if context . Canceled == ctx . Err ( ) {
s . writeError ( ctx , resp , twirp . NewError ( twirp . Canceled , "failed to read request: context canceled" ) )
return
}
if context . DeadlineExceeded == ctx . Err ( ) {
s . writeError ( ctx , resp , twirp . NewError ( twirp . DeadlineExceeded , "failed to read request: deadline exceeded" ) )
return
}
s . writeError ( ctx , resp , twirp . WrapError ( malformedRequestError ( msg ) , err ) )
}
// APIPathPrefix is a convenience constant that may identify URL paths.
// Should be used with caution, it only matches routes generated by Twirp Go clients,
// with the default "/twirp" prefix and default CamelCase service and method names.
// More info: https://twitchtv.github.io/twirp/docs/routing.html
const APIPathPrefix = "/twirp/lure.API/"
func ( s * aPIServer ) ServeHTTP ( resp http . ResponseWriter , req * http . Request ) {
ctx := req . Context ( )
ctx = ctxsetters . WithPackageName ( ctx , "lure" )
ctx = ctxsetters . WithServiceName ( ctx , "API" )
ctx = ctxsetters . WithResponseWriter ( ctx , resp )
var err error
ctx , err = callRequestReceived ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if req . Method != "POST" {
msg := fmt . Sprintf ( "unsupported method %q (only POST is allowed)" , req . Method )
s . writeError ( ctx , resp , badRouteError ( msg , req . Method , req . URL . Path ) )
return
}
// Verify path format: [<prefix>]/<package>.<Service>/<Method>
prefix , pkgService , method := parseTwirpPath ( req . URL . Path )
if pkgService != "lure.API" {
msg := fmt . Sprintf ( "no handler for path %q" , req . URL . Path )
s . writeError ( ctx , resp , badRouteError ( msg , req . Method , req . URL . Path ) )
return
}
if prefix != s . pathPrefix {
msg := fmt . Sprintf ( "invalid path prefix %q, expected %q, on path %q" , prefix , s . pathPrefix , req . URL . Path )
s . writeError ( ctx , resp , badRouteError ( msg , req . Method , req . URL . Path ) )
return
}
switch method {
case "CreateComment" :
s . serveCreateComment ( ctx , resp , req )
return
case "EditComment" :
s . serveEditComment ( ctx , resp , req )
return
case "GetComments" :
s . serveGetComments ( ctx , resp , req )
return
case "Search" :
s . serveSearch ( ctx , resp , req )
return
2022-12-18 07:10:34 +00:00
case "GetPkg" :
s . serveGetPkg ( ctx , resp , req )
return
2022-12-18 05:01:50 +00:00
default :
msg := fmt . Sprintf ( "no handler for path %q" , req . URL . Path )
s . writeError ( ctx , resp , badRouteError ( msg , req . Method , req . URL . Path ) )
return
}
}
func ( s * aPIServer ) serveCreateComment ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
header := req . Header . Get ( "Content-Type" )
i := strings . Index ( header , ";" )
if i == - 1 {
i = len ( header )
}
switch strings . TrimSpace ( strings . ToLower ( header [ : i ] ) ) {
case "application/json" :
s . serveCreateCommentJSON ( ctx , resp , req )
case "application/protobuf" :
s . serveCreateCommentProtobuf ( ctx , resp , req )
default :
msg := fmt . Sprintf ( "unexpected Content-Type: %q" , req . Header . Get ( "Content-Type" ) )
twerr := badRouteError ( msg , req . Method , req . URL . Path )
s . writeError ( ctx , resp , twerr )
}
}
func ( s * aPIServer ) serveCreateCommentJSON ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "CreateComment" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
d := json . NewDecoder ( req . Body )
rawReqBody := json . RawMessage { }
if err := d . Decode ( & rawReqBody ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
reqContent := new ( CreateCommentRequest )
unmarshaler := protojson . UnmarshalOptions { DiscardUnknown : true }
if err = unmarshaler . Unmarshal ( rawReqBody , reqContent ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
handler := s . API . CreateComment
if s . interceptor != nil {
handler = func ( ctx context . Context , req * CreateCommentRequest ) ( * CreateCommentResponse , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * CreateCommentRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*CreateCommentRequest) when calling interceptor" )
}
return s . API . CreateComment ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * CreateCommentResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*CreateCommentResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * CreateCommentResponse
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *CreateCommentResponse and nil error while calling CreateComment. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
marshaler := & protojson . MarshalOptions { UseProtoNames : ! s . jsonCamelCase , EmitUnpopulated : ! s . jsonSkipDefaults }
respBytes , err := marshaler . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal json response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/json" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
func ( s * aPIServer ) serveCreateCommentProtobuf ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "CreateComment" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
buf , err := io . ReadAll ( req . Body )
if err != nil {
s . handleRequestBodyError ( ctx , resp , "failed to read request body" , err )
return
}
reqContent := new ( CreateCommentRequest )
if err = proto . Unmarshal ( buf , reqContent ) ; err != nil {
s . writeError ( ctx , resp , malformedRequestError ( "the protobuf request could not be decoded" ) )
return
}
handler := s . API . CreateComment
if s . interceptor != nil {
handler = func ( ctx context . Context , req * CreateCommentRequest ) ( * CreateCommentResponse , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * CreateCommentRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*CreateCommentRequest) when calling interceptor" )
}
return s . API . CreateComment ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * CreateCommentResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*CreateCommentResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * CreateCommentResponse
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *CreateCommentResponse and nil error while calling CreateComment. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
respBytes , err := proto . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal proto response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/protobuf" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
func ( s * aPIServer ) serveEditComment ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
header := req . Header . Get ( "Content-Type" )
i := strings . Index ( header , ";" )
if i == - 1 {
i = len ( header )
}
switch strings . TrimSpace ( strings . ToLower ( header [ : i ] ) ) {
case "application/json" :
s . serveEditCommentJSON ( ctx , resp , req )
case "application/protobuf" :
s . serveEditCommentProtobuf ( ctx , resp , req )
default :
msg := fmt . Sprintf ( "unexpected Content-Type: %q" , req . Header . Get ( "Content-Type" ) )
twerr := badRouteError ( msg , req . Method , req . URL . Path )
s . writeError ( ctx , resp , twerr )
}
}
func ( s * aPIServer ) serveEditCommentJSON ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "EditComment" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
d := json . NewDecoder ( req . Body )
rawReqBody := json . RawMessage { }
if err := d . Decode ( & rawReqBody ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
reqContent := new ( EditCommentRequest )
unmarshaler := protojson . UnmarshalOptions { DiscardUnknown : true }
if err = unmarshaler . Unmarshal ( rawReqBody , reqContent ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
handler := s . API . EditComment
if s . interceptor != nil {
handler = func ( ctx context . Context , req * EditCommentRequest ) ( * EmptyResponse , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * EditCommentRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*EditCommentRequest) when calling interceptor" )
}
return s . API . EditComment ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * EmptyResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*EmptyResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * EmptyResponse
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *EmptyResponse and nil error while calling EditComment. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
marshaler := & protojson . MarshalOptions { UseProtoNames : ! s . jsonCamelCase , EmitUnpopulated : ! s . jsonSkipDefaults }
respBytes , err := marshaler . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal json response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/json" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
func ( s * aPIServer ) serveEditCommentProtobuf ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "EditComment" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
buf , err := io . ReadAll ( req . Body )
if err != nil {
s . handleRequestBodyError ( ctx , resp , "failed to read request body" , err )
return
}
reqContent := new ( EditCommentRequest )
if err = proto . Unmarshal ( buf , reqContent ) ; err != nil {
s . writeError ( ctx , resp , malformedRequestError ( "the protobuf request could not be decoded" ) )
return
}
handler := s . API . EditComment
if s . interceptor != nil {
handler = func ( ctx context . Context , req * EditCommentRequest ) ( * EmptyResponse , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * EditCommentRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*EditCommentRequest) when calling interceptor" )
}
return s . API . EditComment ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * EmptyResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*EmptyResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * EmptyResponse
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *EmptyResponse and nil error while calling EditComment. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
respBytes , err := proto . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal proto response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/protobuf" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
func ( s * aPIServer ) serveGetComments ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
header := req . Header . Get ( "Content-Type" )
i := strings . Index ( header , ";" )
if i == - 1 {
i = len ( header )
}
switch strings . TrimSpace ( strings . ToLower ( header [ : i ] ) ) {
case "application/json" :
s . serveGetCommentsJSON ( ctx , resp , req )
case "application/protobuf" :
s . serveGetCommentsProtobuf ( ctx , resp , req )
default :
msg := fmt . Sprintf ( "unexpected Content-Type: %q" , req . Header . Get ( "Content-Type" ) )
twerr := badRouteError ( msg , req . Method , req . URL . Path )
s . writeError ( ctx , resp , twerr )
}
}
func ( s * aPIServer ) serveGetCommentsJSON ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "GetComments" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
d := json . NewDecoder ( req . Body )
rawReqBody := json . RawMessage { }
if err := d . Decode ( & rawReqBody ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
reqContent := new ( GetCommentsRequest )
unmarshaler := protojson . UnmarshalOptions { DiscardUnknown : true }
if err = unmarshaler . Unmarshal ( rawReqBody , reqContent ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
handler := s . API . GetComments
if s . interceptor != nil {
handler = func ( ctx context . Context , req * GetCommentsRequest ) ( * GetCommentsResponse , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * GetCommentsRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*GetCommentsRequest) when calling interceptor" )
}
return s . API . GetComments ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * GetCommentsResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*GetCommentsResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * GetCommentsResponse
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *GetCommentsResponse and nil error while calling GetComments. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
marshaler := & protojson . MarshalOptions { UseProtoNames : ! s . jsonCamelCase , EmitUnpopulated : ! s . jsonSkipDefaults }
respBytes , err := marshaler . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal json response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/json" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
func ( s * aPIServer ) serveGetCommentsProtobuf ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "GetComments" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
buf , err := io . ReadAll ( req . Body )
if err != nil {
s . handleRequestBodyError ( ctx , resp , "failed to read request body" , err )
return
}
reqContent := new ( GetCommentsRequest )
if err = proto . Unmarshal ( buf , reqContent ) ; err != nil {
s . writeError ( ctx , resp , malformedRequestError ( "the protobuf request could not be decoded" ) )
return
}
handler := s . API . GetComments
if s . interceptor != nil {
handler = func ( ctx context . Context , req * GetCommentsRequest ) ( * GetCommentsResponse , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * GetCommentsRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*GetCommentsRequest) when calling interceptor" )
}
return s . API . GetComments ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * GetCommentsResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*GetCommentsResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * GetCommentsResponse
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *GetCommentsResponse and nil error while calling GetComments. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
respBytes , err := proto . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal proto response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/protobuf" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
func ( s * aPIServer ) serveSearch ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
header := req . Header . Get ( "Content-Type" )
i := strings . Index ( header , ";" )
if i == - 1 {
i = len ( header )
}
switch strings . TrimSpace ( strings . ToLower ( header [ : i ] ) ) {
case "application/json" :
s . serveSearchJSON ( ctx , resp , req )
case "application/protobuf" :
s . serveSearchProtobuf ( ctx , resp , req )
default :
msg := fmt . Sprintf ( "unexpected Content-Type: %q" , req . Header . Get ( "Content-Type" ) )
twerr := badRouteError ( msg , req . Method , req . URL . Path )
s . writeError ( ctx , resp , twerr )
}
}
func ( s * aPIServer ) serveSearchJSON ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "Search" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
d := json . NewDecoder ( req . Body )
rawReqBody := json . RawMessage { }
if err := d . Decode ( & rawReqBody ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
reqContent := new ( SearchRequest )
unmarshaler := protojson . UnmarshalOptions { DiscardUnknown : true }
if err = unmarshaler . Unmarshal ( rawReqBody , reqContent ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
handler := s . API . Search
if s . interceptor != nil {
handler = func ( ctx context . Context , req * SearchRequest ) ( * SearchResponse , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * SearchRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*SearchRequest) when calling interceptor" )
}
return s . API . Search ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * SearchResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*SearchResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * SearchResponse
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *SearchResponse and nil error while calling Search. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
marshaler := & protojson . MarshalOptions { UseProtoNames : ! s . jsonCamelCase , EmitUnpopulated : ! s . jsonSkipDefaults }
respBytes , err := marshaler . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal json response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/json" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
func ( s * aPIServer ) serveSearchProtobuf ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "Search" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
buf , err := io . ReadAll ( req . Body )
if err != nil {
s . handleRequestBodyError ( ctx , resp , "failed to read request body" , err )
return
}
reqContent := new ( SearchRequest )
if err = proto . Unmarshal ( buf , reqContent ) ; err != nil {
s . writeError ( ctx , resp , malformedRequestError ( "the protobuf request could not be decoded" ) )
return
}
handler := s . API . Search
if s . interceptor != nil {
handler = func ( ctx context . Context , req * SearchRequest ) ( * SearchResponse , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * SearchRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*SearchRequest) when calling interceptor" )
}
return s . API . Search ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * SearchResponse )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*SearchResponse) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * SearchResponse
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *SearchResponse and nil error while calling Search. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
respBytes , err := proto . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal proto response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/protobuf" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
2022-12-18 07:10:34 +00:00
func ( s * aPIServer ) serveGetPkg ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
header := req . Header . Get ( "Content-Type" )
i := strings . Index ( header , ";" )
if i == - 1 {
i = len ( header )
}
switch strings . TrimSpace ( strings . ToLower ( header [ : i ] ) ) {
case "application/json" :
s . serveGetPkgJSON ( ctx , resp , req )
case "application/protobuf" :
s . serveGetPkgProtobuf ( ctx , resp , req )
default :
msg := fmt . Sprintf ( "unexpected Content-Type: %q" , req . Header . Get ( "Content-Type" ) )
twerr := badRouteError ( msg , req . Method , req . URL . Path )
s . writeError ( ctx , resp , twerr )
}
}
func ( s * aPIServer ) serveGetPkgJSON ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "GetPkg" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
d := json . NewDecoder ( req . Body )
rawReqBody := json . RawMessage { }
if err := d . Decode ( & rawReqBody ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
reqContent := new ( GetPackageRequest )
unmarshaler := protojson . UnmarshalOptions { DiscardUnknown : true }
if err = unmarshaler . Unmarshal ( rawReqBody , reqContent ) ; err != nil {
s . handleRequestBodyError ( ctx , resp , "the json request could not be decoded" , err )
return
}
handler := s . API . GetPkg
if s . interceptor != nil {
handler = func ( ctx context . Context , req * GetPackageRequest ) ( * Package , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * GetPackageRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*GetPackageRequest) when calling interceptor" )
}
return s . API . GetPkg ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * Package )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*Package) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * Package
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *Package and nil error while calling GetPkg. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
marshaler := & protojson . MarshalOptions { UseProtoNames : ! s . jsonCamelCase , EmitUnpopulated : ! s . jsonSkipDefaults }
respBytes , err := marshaler . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal json response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/json" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
func ( s * aPIServer ) serveGetPkgProtobuf ( ctx context . Context , resp http . ResponseWriter , req * http . Request ) {
var err error
ctx = ctxsetters . WithMethodName ( ctx , "GetPkg" )
ctx , err = callRequestRouted ( ctx , s . hooks )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
buf , err := io . ReadAll ( req . Body )
if err != nil {
s . handleRequestBodyError ( ctx , resp , "failed to read request body" , err )
return
}
reqContent := new ( GetPackageRequest )
if err = proto . Unmarshal ( buf , reqContent ) ; err != nil {
s . writeError ( ctx , resp , malformedRequestError ( "the protobuf request could not be decoded" ) )
return
}
handler := s . API . GetPkg
if s . interceptor != nil {
handler = func ( ctx context . Context , req * GetPackageRequest ) ( * Package , error ) {
resp , err := s . interceptor (
func ( ctx context . Context , req interface { } ) ( interface { } , error ) {
typedReq , ok := req . ( * GetPackageRequest )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion req.(*GetPackageRequest) when calling interceptor" )
}
return s . API . GetPkg ( ctx , typedReq )
} ,
) ( ctx , req )
if resp != nil {
typedResp , ok := resp . ( * Package )
if ! ok {
return nil , twirp . InternalError ( "failed type assertion resp.(*Package) when calling interceptor" )
}
return typedResp , err
}
return nil , err
}
}
// Call service method
var respContent * Package
func ( ) {
defer ensurePanicResponses ( ctx , resp , s . hooks )
respContent , err = handler ( ctx , reqContent )
} ( )
if err != nil {
s . writeError ( ctx , resp , err )
return
}
if respContent == nil {
s . writeError ( ctx , resp , twirp . InternalError ( "received a nil *Package and nil error while calling GetPkg. nil responses are not supported" ) )
return
}
ctx = callResponsePrepared ( ctx , s . hooks )
respBytes , err := proto . Marshal ( respContent )
if err != nil {
s . writeError ( ctx , resp , wrapInternal ( err , "failed to marshal proto response" ) )
return
}
ctx = ctxsetters . WithStatusCode ( ctx , http . StatusOK )
resp . Header ( ) . Set ( "Content-Type" , "application/protobuf" )
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBytes ) ) )
resp . WriteHeader ( http . StatusOK )
if n , err := resp . Write ( respBytes ) ; err != nil {
msg := fmt . Sprintf ( "failed to write response, %d of %d bytes written: %s" , n , len ( respBytes ) , err . Error ( ) )
twerr := twirp . NewError ( twirp . Unknown , msg )
ctx = callError ( ctx , s . hooks , twerr )
}
callResponseSent ( ctx , s . hooks )
}
2022-12-18 05:01:50 +00:00
func ( s * aPIServer ) ServiceDescriptor ( ) ( [ ] byte , int ) {
return twirpFileDescriptor0 , 0
}
func ( s * aPIServer ) ProtocGenTwirpVersion ( ) string {
return "v8.1.3"
}
// PathPrefix returns the base service path, in the form: "/<prefix>/<package>.<Service>/"
// that is everything in a Twirp route except for the <Method>. This can be used for routing,
// for example to identify the requests that are targeted to this service in a mux.
func ( s * aPIServer ) PathPrefix ( ) string {
return baseServicePath ( s . pathPrefix , "lure" , "API" )
}
// =====
// Utils
// =====
// HTTPClient is the interface used by generated clients to send HTTP requests.
// It is fulfilled by *(net/http).Client, which is sufficient for most users.
// Users can provide their own implementation for special retry policies.
//
// HTTPClient implementations should not follow redirects. Redirects are
// automatically disabled if *(net/http).Client is passed to client
// constructors. See the withoutRedirects function in this file for more
// details.
type HTTPClient interface {
Do ( req * http . Request ) ( * http . Response , error )
}
// TwirpServer is the interface generated server structs will support: they're
// HTTP handlers with additional methods for accessing metadata about the
// service. Those accessors are a low-level API for building reflection tools.
// Most people can think of TwirpServers as just http.Handlers.
type TwirpServer interface {
http . Handler
// ServiceDescriptor returns gzipped bytes describing the .proto file that
// this service was generated from. Once unzipped, the bytes can be
// unmarshalled as a
// google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto.
//
// The returned integer is the index of this particular service within that
// FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a
// low-level field, expected to be used for reflection.
ServiceDescriptor ( ) ( [ ] byte , int )
// ProtocGenTwirpVersion is the semantic version string of the version of
// twirp used to generate this file.
ProtocGenTwirpVersion ( ) string
// PathPrefix returns the HTTP URL path prefix for all methods handled by this
// service. This can be used with an HTTP mux to route Twirp requests.
// The path prefix is in the form: "/<prefix>/<package>.<Service>/"
// that is, everything in a Twirp route except for the <Method> at the end.
PathPrefix ( ) string
}
func newServerOpts ( opts [ ] interface { } ) * twirp . ServerOptions {
serverOpts := & twirp . ServerOptions { }
for _ , opt := range opts {
switch o := opt . ( type ) {
case twirp . ServerOption :
o ( serverOpts )
case * twirp . ServerHooks : // backwards compatibility, allow to specify hooks as an argument
twirp . WithServerHooks ( o ) ( serverOpts )
case nil : // backwards compatibility, allow nil value for the argument
continue
default :
panic ( fmt . Sprintf ( "Invalid option type %T, please use a twirp.ServerOption" , o ) )
}
}
return serverOpts
}
// WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta).
// Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks.
// If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err)
func WriteError ( resp http . ResponseWriter , err error ) {
writeError ( context . Background ( ) , resp , err , nil )
}
// writeError writes Twirp errors in the response and triggers hooks.
func writeError ( ctx context . Context , resp http . ResponseWriter , err error , hooks * twirp . ServerHooks ) {
// Convert to a twirp.Error. Non-twirp errors are converted to internal errors.
var twerr twirp . Error
if ! errors . As ( err , & twerr ) {
twerr = twirp . InternalErrorWith ( err )
}
statusCode := twirp . ServerHTTPStatusFromErrorCode ( twerr . Code ( ) )
ctx = ctxsetters . WithStatusCode ( ctx , statusCode )
ctx = callError ( ctx , hooks , twerr )
respBody := marshalErrorToJSON ( twerr )
resp . Header ( ) . Set ( "Content-Type" , "application/json" ) // Error responses are always JSON
resp . Header ( ) . Set ( "Content-Length" , strconv . Itoa ( len ( respBody ) ) )
resp . WriteHeader ( statusCode ) // set HTTP status code and send response
_ , writeErr := resp . Write ( respBody )
if writeErr != nil {
// We have three options here. We could log the error, call the Error
// hook, or just silently ignore the error.
//
// Logging is unacceptable because we don't have a user-controlled
// logger; writing out to stderr without permission is too rude.
//
// Calling the Error hook would confuse users: it would mean the Error
// hook got called twice for one request, which is likely to lead to
// duplicated log messages and metrics, no matter how well we document
// the behavior.
//
// Silently ignoring the error is our least-bad option. It's highly
// likely that the connection is broken and the original 'err' says
// so anyway.
_ = writeErr
}
callResponseSent ( ctx , hooks )
}
// sanitizeBaseURL parses the the baseURL, and adds the "http" scheme if needed.
// If the URL is unparsable, the baseURL is returned unchanged.
func sanitizeBaseURL ( baseURL string ) string {
u , err := url . Parse ( baseURL )
if err != nil {
return baseURL // invalid URL will fail later when making requests
}
if u . Scheme == "" {
u . Scheme = "http"
}
return u . String ( )
}
// baseServicePath composes the path prefix for the service (without <Method>).
// e.g.: baseServicePath("/twirp", "my.pkg", "MyService")
//
// returns => "/twirp/my.pkg.MyService/"
//
// e.g.: baseServicePath("", "", "MyService")
//
// returns => "/MyService/"
func baseServicePath ( prefix , pkg , service string ) string {
fullServiceName := service
if pkg != "" {
fullServiceName = pkg + "." + service
}
return path . Join ( "/" , prefix , fullServiceName ) + "/"
}
// parseTwirpPath extracts path components form a valid Twirp route.
// Expected format: "[<prefix>]/<package>.<Service>/<Method>"
// e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat")
func parseTwirpPath ( path string ) ( string , string , string ) {
parts := strings . Split ( path , "/" )
if len ( parts ) < 2 {
return "" , "" , ""
}
method := parts [ len ( parts ) - 1 ]
pkgService := parts [ len ( parts ) - 2 ]
prefix := strings . Join ( parts [ 0 : len ( parts ) - 2 ] , "/" )
return prefix , pkgService , method
}
// getCustomHTTPReqHeaders retrieves a copy of any headers that are set in
// a context through the twirp.WithHTTPRequestHeaders function.
// If there are no headers set, or if they have the wrong type, nil is returned.
func getCustomHTTPReqHeaders ( ctx context . Context ) http . Header {
header , ok := twirp . HTTPRequestHeaders ( ctx )
if ! ok || header == nil {
return nil
}
copied := make ( http . Header )
for k , vv := range header {
if vv == nil {
copied [ k ] = nil
continue
}
copied [ k ] = make ( [ ] string , len ( vv ) )
copy ( copied [ k ] , vv )
}
return copied
}
// newRequest makes an http.Request from a client, adding common headers.
func newRequest ( ctx context . Context , url string , reqBody io . Reader , contentType string ) ( * http . Request , error ) {
req , err := http . NewRequest ( "POST" , url , reqBody )
if err != nil {
return nil , err
}
req = req . WithContext ( ctx )
if customHeader := getCustomHTTPReqHeaders ( ctx ) ; customHeader != nil {
req . Header = customHeader
}
req . Header . Set ( "Accept" , contentType )
req . Header . Set ( "Content-Type" , contentType )
req . Header . Set ( "Twirp-Version" , "v8.1.3" )
return req , nil
}
// JSON serialization for errors
type twerrJSON struct {
Code string ` json:"code" `
Msg string ` json:"msg" `
Meta map [ string ] string ` json:"meta,omitempty" `
}
// marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body.
// If serialization fails, it will use a descriptive Internal error instead.
func marshalErrorToJSON ( twerr twirp . Error ) [ ] byte {
// make sure that msg is not too large
msg := twerr . Msg ( )
if len ( msg ) > 1e6 {
msg = msg [ : 1e6 ]
}
tj := twerrJSON {
Code : string ( twerr . Code ( ) ) ,
Msg : msg ,
Meta : twerr . MetaMap ( ) ,
}
buf , err := json . Marshal ( & tj )
if err != nil {
buf = [ ] byte ( "{\"type\": \"" + twirp . Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}" ) // fallback
}
return buf
}
// errorFromResponse builds a twirp.Error from a non-200 HTTP response.
// If the response has a valid serialized Twirp error, then it's returned.
// If not, the response status code is used to generate a similar twirp
// error. See twirpErrorFromIntermediary for more info on intermediary errors.
func errorFromResponse ( resp * http . Response ) twirp . Error {
statusCode := resp . StatusCode
statusText := http . StatusText ( statusCode )
if isHTTPRedirect ( statusCode ) {
// Unexpected redirect: it must be an error from an intermediary.
// Twirp clients don't follow redirects automatically, Twirp only handles
// POST requests, redirects should only happen on GET and HEAD requests.
location := resp . Header . Get ( "Location" )
msg := fmt . Sprintf ( "unexpected HTTP status code %d %q received, Location=%q" , statusCode , statusText , location )
return twirpErrorFromIntermediary ( statusCode , msg , location )
}
respBodyBytes , err := io . ReadAll ( resp . Body )
if err != nil {
return wrapInternal ( err , "failed to read server error response body" )
}
var tj twerrJSON
dec := json . NewDecoder ( bytes . NewReader ( respBodyBytes ) )
dec . DisallowUnknownFields ( )
if err := dec . Decode ( & tj ) ; err != nil || tj . Code == "" {
// Invalid JSON response; it must be an error from an intermediary.
msg := fmt . Sprintf ( "Error from intermediary with HTTP status code %d %q" , statusCode , statusText )
return twirpErrorFromIntermediary ( statusCode , msg , string ( respBodyBytes ) )
}
errorCode := twirp . ErrorCode ( tj . Code )
if ! twirp . IsValidErrorCode ( errorCode ) {
msg := "invalid type returned from server error response: " + tj . Code
return twirp . InternalError ( msg ) . WithMeta ( "body" , string ( respBodyBytes ) )
}
twerr := twirp . NewError ( errorCode , tj . Msg )
for k , v := range tj . Meta {
twerr = twerr . WithMeta ( k , v )
}
return twerr
}
// twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors.
// The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md.
// Returned twirp Errors have some additional metadata for inspection.
func twirpErrorFromIntermediary ( status int , msg string , bodyOrLocation string ) twirp . Error {
var code twirp . ErrorCode
if isHTTPRedirect ( status ) { // 3xx
code = twirp . Internal
} else {
switch status {
case 400 : // Bad Request
code = twirp . Internal
case 401 : // Unauthorized
code = twirp . Unauthenticated
case 403 : // Forbidden
code = twirp . PermissionDenied
case 404 : // Not Found
code = twirp . BadRoute
case 429 : // Too Many Requests
code = twirp . ResourceExhausted
case 502 , 503 , 504 : // Bad Gateway, Service Unavailable, Gateway Timeout
code = twirp . Unavailable
default : // All other codes
code = twirp . Unknown
}
}
twerr := twirp . NewError ( code , msg )
twerr = twerr . WithMeta ( "http_error_from_intermediary" , "true" ) // to easily know if this error was from intermediary
twerr = twerr . WithMeta ( "status_code" , strconv . Itoa ( status ) )
if isHTTPRedirect ( status ) {
twerr = twerr . WithMeta ( "location" , bodyOrLocation )
} else {
twerr = twerr . WithMeta ( "body" , bodyOrLocation )
}
return twerr
}
func isHTTPRedirect ( status int ) bool {
return status >= 300 && status <= 399
}
// wrapInternal wraps an error with a prefix as an Internal error.
// The original error cause is accessible by github.com/pkg/errors.Cause.
func wrapInternal ( err error , prefix string ) twirp . Error {
return twirp . InternalErrorWith ( & wrappedError { prefix : prefix , cause : err } )
}
type wrappedError struct {
prefix string
cause error
}
func ( e * wrappedError ) Error ( ) string { return e . prefix + ": " + e . cause . Error ( ) }
func ( e * wrappedError ) Unwrap ( ) error { return e . cause } // for go1.13 + errors.Is/As
func ( e * wrappedError ) Cause ( ) error { return e . cause } // for github.com/pkg/errors
// ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal
// error response (status 500), and error hooks are properly called with the panic wrapped as an error.
// The panic is re-raised so it can be handled normally with middleware.
func ensurePanicResponses ( ctx context . Context , resp http . ResponseWriter , hooks * twirp . ServerHooks ) {
if r := recover ( ) ; r != nil {
// Wrap the panic as an error so it can be passed to error hooks.
// The original error is accessible from error hooks, but not visible in the response.
err := errFromPanic ( r )
twerr := & internalWithCause { msg : "Internal service panic" , cause : err }
// Actually write the error
writeError ( ctx , resp , twerr , hooks )
// If possible, flush the error to the wire.
f , ok := resp . ( http . Flusher )
if ok {
f . Flush ( )
}
panic ( r )
}
}
// errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error.
func errFromPanic ( p interface { } ) error {
if err , ok := p . ( error ) ; ok {
return err
}
return fmt . Errorf ( "panic: %v" , p )
}
// internalWithCause is a Twirp Internal error wrapping an original error cause,
// but the original error message is not exposed on Msg(). The original error
// can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap
type internalWithCause struct {
msg string
cause error
}
func ( e * internalWithCause ) Unwrap ( ) error { return e . cause } // for go1.13 + errors.Is/As
func ( e * internalWithCause ) Cause ( ) error { return e . cause } // for github.com/pkg/errors
func ( e * internalWithCause ) Error ( ) string { return e . msg + ": " + e . cause . Error ( ) }
func ( e * internalWithCause ) Code ( ) twirp . ErrorCode { return twirp . Internal }
func ( e * internalWithCause ) Msg ( ) string { return e . msg }
func ( e * internalWithCause ) Meta ( key string ) string { return "" }
func ( e * internalWithCause ) MetaMap ( ) map [ string ] string { return nil }
func ( e * internalWithCause ) WithMeta ( key string , val string ) twirp . Error { return e }
// malformedRequestError is used when the twirp server cannot unmarshal a request
func malformedRequestError ( msg string ) twirp . Error {
return twirp . NewError ( twirp . Malformed , msg )
}
// badRouteError is used when the twirp server cannot route a request
func badRouteError ( msg string , method , url string ) twirp . Error {
err := twirp . NewError ( twirp . BadRoute , msg )
err = err . WithMeta ( "twirp_invalid_route" , method + " " + url )
return err
}
// withoutRedirects makes sure that the POST request can not be redirected.
// The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or
// 303 response, and also 301s in go1.8. It redirects by making a second request, changing the
// method to GET and removing the body. This produces very confusing error messages, so instead we
// set a redirect policy that always errors. This stops Go from executing the redirect.
//
// We have to be a little careful in case the user-provided http.Client has its own CheckRedirect
// policy - if so, we'll run through that policy first.
//
// Because this requires modifying the http.Client, we make a new copy of the client and return it.
func withoutRedirects ( in * http . Client ) * http . Client {
copy := * in
copy . CheckRedirect = func ( req * http . Request , via [ ] * http . Request ) error {
if in . CheckRedirect != nil {
// Run the input's redirect if it exists, in case it has side effects, but ignore any error it
// returns, since we want to use ErrUseLastResponse.
err := in . CheckRedirect ( req , via )
_ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use.
}
return http . ErrUseLastResponse
}
return & copy
}
// doProtobufRequest makes a Protobuf request to the remote Twirp service.
func doProtobufRequest ( ctx context . Context , client HTTPClient , hooks * twirp . ClientHooks , url string , in , out proto . Message ) ( _ context . Context , err error ) {
reqBodyBytes , err := proto . Marshal ( in )
if err != nil {
return ctx , wrapInternal ( err , "failed to marshal proto request" )
}
reqBody := bytes . NewBuffer ( reqBodyBytes )
if err = ctx . Err ( ) ; err != nil {
return ctx , wrapInternal ( err , "aborted because context was done" )
}
req , err := newRequest ( ctx , url , reqBody , "application/protobuf" )
if err != nil {
return ctx , wrapInternal ( err , "could not build request" )
}
ctx , err = callClientRequestPrepared ( ctx , hooks , req )
if err != nil {
return ctx , err
}
req = req . WithContext ( ctx )
resp , err := client . Do ( req )
if err != nil {
return ctx , wrapInternal ( err , "failed to do request" )
}
defer func ( ) { _ = resp . Body . Close ( ) } ( )
if err = ctx . Err ( ) ; err != nil {
return ctx , wrapInternal ( err , "aborted because context was done" )
}
if resp . StatusCode != 200 {
return ctx , errorFromResponse ( resp )
}
respBodyBytes , err := io . ReadAll ( resp . Body )
if err != nil {
return ctx , wrapInternal ( err , "failed to read response body" )
}
if err = ctx . Err ( ) ; err != nil {
return ctx , wrapInternal ( err , "aborted because context was done" )
}
if err = proto . Unmarshal ( respBodyBytes , out ) ; err != nil {
return ctx , wrapInternal ( err , "failed to unmarshal proto response" )
}
return ctx , nil
}
// doJSONRequest makes a JSON request to the remote Twirp service.
func doJSONRequest ( ctx context . Context , client HTTPClient , hooks * twirp . ClientHooks , url string , in , out proto . Message ) ( _ context . Context , err error ) {
marshaler := & protojson . MarshalOptions { UseProtoNames : true }
reqBytes , err := marshaler . Marshal ( in )
if err != nil {
return ctx , wrapInternal ( err , "failed to marshal json request" )
}
if err = ctx . Err ( ) ; err != nil {
return ctx , wrapInternal ( err , "aborted because context was done" )
}
req , err := newRequest ( ctx , url , bytes . NewReader ( reqBytes ) , "application/json" )
if err != nil {
return ctx , wrapInternal ( err , "could not build request" )
}
ctx , err = callClientRequestPrepared ( ctx , hooks , req )
if err != nil {
return ctx , err
}
req = req . WithContext ( ctx )
resp , err := client . Do ( req )
if err != nil {
return ctx , wrapInternal ( err , "failed to do request" )
}
defer func ( ) {
cerr := resp . Body . Close ( )
if err == nil && cerr != nil {
err = wrapInternal ( cerr , "failed to close response body" )
}
} ( )
if err = ctx . Err ( ) ; err != nil {
return ctx , wrapInternal ( err , "aborted because context was done" )
}
if resp . StatusCode != 200 {
return ctx , errorFromResponse ( resp )
}
d := json . NewDecoder ( resp . Body )
rawRespBody := json . RawMessage { }
if err := d . Decode ( & rawRespBody ) ; err != nil {
return ctx , wrapInternal ( err , "failed to unmarshal json response" )
}
unmarshaler := protojson . UnmarshalOptions { DiscardUnknown : true }
if err = unmarshaler . Unmarshal ( rawRespBody , out ) ; err != nil {
return ctx , wrapInternal ( err , "failed to unmarshal json response" )
}
if err = ctx . Err ( ) ; err != nil {
return ctx , wrapInternal ( err , "aborted because context was done" )
}
return ctx , nil
}
// Call twirp.ServerHooks.RequestReceived if the hook is available
func callRequestReceived ( ctx context . Context , h * twirp . ServerHooks ) ( context . Context , error ) {
if h == nil || h . RequestReceived == nil {
return ctx , nil
}
return h . RequestReceived ( ctx )
}
// Call twirp.ServerHooks.RequestRouted if the hook is available
func callRequestRouted ( ctx context . Context , h * twirp . ServerHooks ) ( context . Context , error ) {
if h == nil || h . RequestRouted == nil {
return ctx , nil
}
return h . RequestRouted ( ctx )
}
// Call twirp.ServerHooks.ResponsePrepared if the hook is available
func callResponsePrepared ( ctx context . Context , h * twirp . ServerHooks ) context . Context {
if h == nil || h . ResponsePrepared == nil {
return ctx
}
return h . ResponsePrepared ( ctx )
}
// Call twirp.ServerHooks.ResponseSent if the hook is available
func callResponseSent ( ctx context . Context , h * twirp . ServerHooks ) {
if h == nil || h . ResponseSent == nil {
return
}
h . ResponseSent ( ctx )
}
// Call twirp.ServerHooks.Error if the hook is available
func callError ( ctx context . Context , h * twirp . ServerHooks , err twirp . Error ) context . Context {
if h == nil || h . Error == nil {
return ctx
}
return h . Error ( ctx , err )
}
func callClientResponseReceived ( ctx context . Context , h * twirp . ClientHooks ) {
if h == nil || h . ResponseReceived == nil {
return
}
h . ResponseReceived ( ctx )
}
func callClientRequestPrepared ( ctx context . Context , h * twirp . ClientHooks , req * http . Request ) ( context . Context , error ) {
if h == nil || h . RequestPrepared == nil {
return ctx , nil
}
return h . RequestPrepared ( ctx , req )
}
func callClientError ( ctx context . Context , h * twirp . ClientHooks , err twirp . Error ) {
if h == nil || h . Error == nil {
return
}
h . Error ( ctx , err )
}
var twirpFileDescriptor0 = [ ] byte {
2022-12-18 07:10:34 +00:00
// 978 bytes of a gzipped FileDescriptorProto
0x1f , 0x8b , 0x08 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x02 , 0xff , 0xac , 0x56 , 0xef , 0x6e , 0xe3 , 0x44 ,
0x10 , 0xaf , 0x93 , 0x26 , 0x4e , 0xc6 , 0x71 , 0x9a , 0xee , 0x15 , 0xe1 , 0x86 , 0x3f , 0x57 , 0x7c , 0x50 ,
0x95 , 0xfb , 0xd0 , 0x43 , 0x3d , 0x84 , 0x10 , 0x20 , 0x44 , 0xdd , 0x86 , 0x36 , 0x52 , 0x49 , 0xc2 , 0x26 ,
0x57 , 0xa9 , 0x7c , 0xb1 , 0x5c , 0x67 , 0x2e , 0x5d , 0xc5 , 0xff , 0xce , 0xde , 0xf4 , 0x94 , 0x37 , 0x38 ,
0xf1 , 0x44 , 0x3c , 0x06 , 0x0f , 0xc1 , 0x83 , 0xa0 , 0xdd , 0xb5 , 0x53 , 0xa7 , 0xad , 0x38 , 0x09 , 0xf8 ,
0xb6 , 0xf3 , 0x9b , 0x7f , 0x3b , 0x33 , 0x3f , 0xcf , 0x1a , 0x20 , 0x58 , 0xa4 , 0x78 , 0x98 , 0xa4 , 0x31 ,
0x8f , 0xc9 , 0xa6 , 0x38 , 0xdb , 0x5b , 0x60 , 0xf6 , 0xc2 , 0x84 , 0x2f , 0x29 , 0x66 , 0x49 , 0x1c , 0x65 ,
0x68 , 0xcf , 0x40 , 0x3f , 0x89 , 0xc3 , 0x10 , 0x23 , 0x4e , 0x3e , 0x01 , 0xf0 , 0xd5 , 0xd1 , 0x65 , 0x53 ,
0x4b , 0xdb , 0xd3 , 0x0e , 0xaa , 0xb4 , 0x99 , 0x23 , 0xfd , 0x29 , 0xf9 , 0x0c , 0x5a , 0x9c , 0x85 , 0xe8 ,
0xfa , 0x29 , 0x7a , 0x1c , 0xa7 , 0x56 , 0x45 , 0x1a , 0x18 , 0x02 , 0x3b , 0x51 , 0x10 , 0xe9 , 0x42 , 0xc3 ,
0x8f , 0x23 , 0x8e , 0x11 , 0xcf , 0xac , 0xea , 0x9e , 0x76 , 0xd0 , 0xa4 , 0x2b , 0xd9 , 0x0e , 0x61 , 0x47 ,
0x99 , 0xe5 , 0xe9 , 0x28 , 0xbe , 0x59 , 0x60 , 0xc6 , 0xc9 , 0xa7 , 0x00 , 0x29 , 0x26 , 0x71 , 0xc6 , 0x78 ,
0x9c , 0x2e , 0x65 , 0xd6 , 0x26 , 0x2d , 0x21 , 0x64 , 0x17 , 0x1a , 0xc9 , 0x7c , 0xe6 , 0x46 , 0x5e , 0x88 ,
0x32 , 0x65 , 0x93 , 0xea , 0xc9 , 0x7c , 0x36 , 0xf0 , 0x42 , 0xfc , 0xc7 , 0x74 , 0xdf , 0xc0 , 0x07 , 0xf7 ,
0xd2 , 0xa9 , 0x82 , 0xdf , 0x53 , 0xa5 , 0x7d , 0x09 , 0xa4 , 0x37 , 0x65 , 0xfc , 0xde , 0x25 , 0xdf , 0xdf ,
0x9a , 0x08 , 0xdf , 0xba , 0xab , 0xcb , 0xa8 , 0x7b , 0x1a , 0x11 , 0xbe , 0x3d , 0x29 , 0xee , 0xf3 , 0xbb ,
0x06 , 0xe4 , 0x0c , 0x8b , 0xb8 , 0xd9 , 0xff , 0x50 , 0xfd , 0x33 , 0x30 , 0xf3 , 0x51 , 0xb8 , 0x19 , 0x8b ,
0x7c , 0x94 , 0x2d , 0xa8 , 0xd2 , 0x56 , 0x0e , 0x8e , 0x05 , 0x46 , 0x76 , 0xa0 , 0x16 , 0xb0 , 0x90 , 0x71 ,
0x6b , 0x53 , 0x2a , 0x95 , 0x60 , 0xff , 0x04 , 0x4f , 0xd6 , 0xee , 0x92 , 0xb7 , 0xe6 , 0x4b , 0xd1 , 0x4f ,
0x85 , 0x59 , 0xda , 0x5e , 0xf5 , 0xc0 , 0x38 , 0x32 , 0x0f , 0x25 , 0x83 , 0x8a , 0x6e , 0xac , 0xd4 , 0xf6 ,
0x9f , 0x1a , 0x98 , 0x63 , 0xf4 , 0x52 , 0xff , 0xa6 , 0xa8 , 0x64 , 0x07 , 0x6a , 0x6f , 0x16 , 0xb8 , 0x2a ,
0x42 , 0x09 , 0x77 , 0xf9 , 0x2b , 0xa5 , 0xfc , 0x64 , 0x1f , 0xf4 , 0x2c , 0x4e , 0xb9 , 0x7b , 0xbd , 0x94 ,
0x97 , 0x6e , 0x17 , 0x79 , 0xc6 , 0x43 , 0x3a , 0x71 , 0x9d , 0x2b , 0x5a , 0x17 , 0x5a , 0x67 , 0x49 , 0x8e ,
0xc0 , 0x78 , 0xcd , 0x02 , 0x8e , 0xa9 , 0xcb , 0x97 , 0x09 , 0xca , 0x1a , 0xda , 0x47 , 0xdb , 0xca , 0xf6 ,
0xe7 , 0xfe , 0xc5 , 0xa4 , 0x47 , 0xdd , 0xc9 , 0xd5 , 0xa8 , 0x47 , 0x41 , 0x59 , 0x4d , 0x96 , 0x09 , 0x92 ,
0x7d , 0x68 , 0xe5 , 0x3e , 0xb7 , 0x5e , 0xb0 , 0x40 , 0xab , 0x26 , 0xae , 0x73 , 0xbe , 0x41 , 0xf3 , 0x48 ,
0x97 , 0x02 , 0x7c , 0xa7 , 0x69 , 0xce , 0x16 , 0x98 , 0x6e , 0xd9 , 0xd0 , 0xde , 0x07 , 0x18 , 0xf3 , 0x94 ,
0x45 , 0xb3 , 0x0b , 0x96 , 0x71 , 0x62 , 0x81 , 0x8e , 0x11 , 0x4f , 0x19 , 0xaa , 0x56 , 0x34 , 0x69 , 0x21 ,
0xda , 0x7f , 0xd5 , 0x40 , 0x1f , 0x79 , 0xfe , 0xdc , 0x9b , 0x21 , 0x21 , 0xb0 , 0x29 , 0x47 , 0xa3 , 0x6a ,
0x96 , 0xe7 , 0x7b , 0x23 , 0xad , 0x3c , 0x18 , 0xa9 , 0x05 , 0xfa , 0x2d , 0xa6 , 0x19 , 0x8b , 0xa3 , 0x9c ,
0xb4 , 0x85 , 0x28 , 0x34 , 0x29 , 0x06 , 0xe8 , 0x65 , 0x98 , 0x8f , 0xab , 0x10 , 0xc9 , 0x2e , 0xd4 , 0x30 ,
0x89 , 0xfd , 0x1b , 0x59 , 0x4d , 0xf5 , 0x7c , 0x83 , 0x2a , 0xf1 , 0x9d , 0xa6 , 0x91 , 0x2f , 0xc0 , 0x98 ,
0x62 , 0xe6 , 0xa7 , 0x2c , 0xe1 , 0x22 , 0x64 , 0x5d , 0x96 , 0xab , 0xd1 , 0x32 , 0x28 , 0xcc , 0x9e , 0x42 ,
0xe3 , 0x26 , 0x0e , 0x31 , 0xf1 , 0x66 , 0x68 , 0xe9 , 0xd2 , 0xa6 , 0x42 , 0x57 , 0x88 , 0x30 , 0x78 , 0x06 ,
0x10 , 0x7a , 0x2c , 0xe2 , 0x1e , 0x8b , 0x30 , 0xb5 , 0x1a , 0xd2 , 0xa4 , 0x4a , 0x4b , 0x98 , 0x30 , 0xfa ,
0x1c , 0x4c , 0x31 , 0x73 , 0xc6 , 0xd1 , 0xe7 , 0x8b , 0x14 , 0x33 , 0xab , 0x29 , 0x7b , 0xb3 , 0x0e , 0x8a ,
0xef , 0x32 , 0x60 , 0x3e , 0x46 , 0x19 , 0x66 , 0x16 , 0x48 , 0x83 , 0x95 , 0x2c , 0x74 , 0x49 , 0x1a , 0xdf ,
0xb2 , 0x29 , 0x66 , 0x96 , 0xa1 , 0x74 , 0x85 , 0x4c , 0x3e , 0x86 , 0xa6 , 0x1f , 0x47 , 0xaf , 0x03 , 0xe6 ,
0xf3 , 0xcc , 0x6a , 0x49 , 0xe5 , 0x1d , 0x20 , 0x3c , 0x53 , 0x4c , 0x02 , 0xcf , 0xc7 , 0xcc , 0x32 , 0x95 ,
0x67 , 0x21 , 0x93 , 0xaf , 0x41 , 0x9f , 0x62 , 0x82 , 0xd1 , 0x34 , 0xb3 , 0xda , 0x92 , 0xb8 , 0x5d , 0x45 ,
0x92 , 0x7c , 0x4e , 0x87 , 0xa7 , 0x4a , 0xd9 , 0x8b , 0x78 , 0xba , 0xa4 , 0x85 , 0x29 , 0x39 , 0x05 , 0xf3 ,
0x7a , 0xc1 , 0x82 , 0xa9 , 0x5b , 0xf8 , 0x6e , 0x49 , 0xdf , 0xa7 , 0xeb , 0xbe , 0x8e , 0x30 , 0x59 , 0x0b ,
0xd0 , 0xba , 0x2e , 0x41 , 0xdd , 0x0b , 0x68 , 0x95 , 0xb5 , 0xa4 , 0x03 , 0xd5 , 0x39 , 0x16 , 0x9f , 0x81 ,
0x38 , 0x92 , 0x7d , 0xa8 , 0x29 , 0x2e , 0x0a , 0x32 , 0x18 , 0x47 , 0x9d , 0x9c , 0xec , 0x2b , 0xb2 , 0x51 ,
0xa5 , 0xfe , 0xae , 0xf2 , 0xad , 0xd6 , 0xfd , 0x15 , 0xb6 , 0x1f , 0x24 , 0xfc , 0x6f , 0x21 , 0x9d , 0x06 ,
0xd4 , 0x5d , 0x49 , 0x17 , 0xa7 , 0x0d , 0x2d , 0xb7 , 0xc4 , 0x0b , 0xc7 , 0x80 , 0xa6 , 0x5b , 0x70 , 0xc0 ,
0x31 , 0xc1 , 0x70 , 0xef , 0xa6 , 0x6d , 0x9f , 0xc1 , 0xf6 , 0x19 , 0xf2 , 0xbc , 0x09 , 0xc5 , 0x47 , 0xfe ,
0x2f , 0xf8 , 0x6e , 0x7f , 0x0f , 0xed , 0x62 , 0x53 , 0xdc , 0xed , 0x99 , 0x44 , 0xc5 , 0xbd , 0xb7 , 0x67 ,
0x8a , 0x6c , 0x2b , 0xf5 , 0xf3 , 0x1f , 0x41 , 0xcf , 0x97 , 0x02 , 0x69 , 0x41 , 0xe3 , 0xd5 , 0x40 , 0x08 ,
0xbd , 0xd3 , 0xce , 0x06 , 0x69 , 0xc0 , 0xe6 , 0xe0 , 0xf8 , 0x97 , 0x5e , 0x47 , 0x23 , 0x6d , 0x00 , 0xda ,
0x1b , 0x0d , 0xc7 , 0xfd , 0xc9 , 0x90 , 0x5e , 0x75 , 0x2a , 0xc4 , 0x00 , 0xfd , 0xb2 , 0x47 , 0xc7 , 0xfd ,
0xe1 , 0xa0 , 0x53 , 0x7d , 0xee , 0x80 , 0x51 , 0x5a , 0x14 , 0xc4 , 0x84 , 0xe6 , 0x60 , 0xe8 , 0x2a , 0xa4 ,
0xb3 , 0x41 , 0xb6 , 0xc1 , 0xec , 0x0f , 0xdc , 0x92 , 0xb7 , 0x26 , 0xa0 , 0xf1 , 0xab , 0xd1 , 0x68 , 0x48 ,
0x27 , 0x63 , 0xf7 , 0x98 , 0x9e , 0x9c , 0x77 , 0x2a , 0x47 , 0x7f , 0x54 , 0xa0 , 0x7a , 0x3c , 0xea , 0x93 ,
0x73 , 0x30 , 0xd7 , 0x9e , 0x14 , 0x92 , 0x93 , 0xec , 0xb1 , 0x67 , 0xad , 0xfb , 0xd1 , 0xa3 , 0xba , 0xbc ,
0x01 , 0x3f , 0x80 , 0x51 , 0x7a , 0x64 , 0x88 , 0xa5 , 0x6c , 0x1f , 0xbe , 0x3b , 0xdd , 0x27 , 0xb9 , 0xa6 ,
0xfc , 0x64 , 0x13 , 0x07 , 0x8c , 0xd2 , 0xf6 , 0x2e , 0xbc , 0x1f , 0x3e , 0x2e , 0xdd , 0xdd , 0x47 , 0x34 ,
0x79 , 0x8c , 0x97 , 0x50 , 0x57 , 0x43 , 0x21 , 0x79 , 0x8a , 0xb5 , 0x65 , 0xde , 0xdd , 0x59 , 0x07 , 0x73 ,
0xa7 , 0xaf , 0xa0 , 0x2e , 0x28 , 0x31 , 0x9f , 0x91 , 0x0f , 0x57 , 0x91 , 0xd7 , 0x09 , 0xd2 , 0x5d , 0x1f ,
0xa4 , 0xb3 , 0xf5 , 0x9b , 0xf9 , 0x82 , 0x45 , 0x1c , 0xd3 , 0xc8 , 0x0b , 0x5e , 0x78 , 0x09 , 0xbb , 0xae ,
0xcb , 0x9f , 0x91 , 0x97 , 0x7f , 0x07 , 0x00 , 0x00 , 0xff , 0xff , 0xec , 0xa6 , 0x81 , 0xb1 , 0x9a , 0x08 ,
0x00 , 0x00 ,
2022-12-18 05:01:50 +00:00
}