Documentation ¶
Overview ¶
Package typed provides for the capability of having typed handlers (methods/functions) for api endpoints
to utilise typed handlers, just set the MethodHandlerBuilder in chioas.Definition
For full documentation - see https://github.com/go-andiamo/chioas/blob/main/typed/README.md
Example:
package main import ( "github.com/go-andiamo/chioas" "github.com/go-andiamo/chioas/typed" "github.com/go-chi/chi/v5" "net/http" ) var def = chioas.Definition{ DocOptions: chioas.DocOptions{ ServeDocs: true, }, MethodHandlerBuilder: typed.NewTypedMethodsHandlerBuilder(nil), Methods: map[string]chioas.Method{ http.MethodGet: { Handler: func() (map[string]any, error) { return map[string]any{ "root": "root discovery", }, nil }, }, }, Paths: map[string]chioas.Path{ "/people": { Methods: map[string]chioas.Method{ http.MethodGet: { Handler: "GetPeople", Responses: chioas.Responses{ http.StatusOK: { IsArray: true, SchemaRef: "Person", }, }, }, http.MethodPost: { Handler: "AddPerson", Request: &chioas.Request{ Schema: personSchema, }, Responses: chioas.Responses{ http.StatusOK: { SchemaRef: "Person", }, }, }, }, }, }, Components: &chioas.Components{ Schemas: chioas.Schemas{ personSchema, }, }, } type api struct { chioas.Definition } var myApi = &api{ Definition: def, } func (a *api) SetupRoutes(r chi.Router) error { return a.Definition.SetupRoutes(r, a) } type Person struct { Id int `json:"id" oas:"description:The id of the person,example"` Name string `json:"name" oas:"description:The name of the person,example"` } var personSchema = (&chioas.Schema{ Name: "Person", }).Must(Person{ Id: 1, Name: "Bilbo", }) // GetPeople is the typed handler for GET /people - note the typed return args func (a *api) GetPeople() ([]Person, error) { return []Person{ { Id: 0, Name: "Me", }, { Id: 1, Name: "You", }, }, nil } // AddPerson is the typed handler for POST /person - note the typed input and return args func (a *api) AddPerson(person *Person) (Person, error) { return *person, nil } func main() { router := chi.NewRouter() if err := myApi.SetupRoutes(router); err != nil { panic(err) } _ = http.ListenAndServe(":8080", router) }
Index ¶
- func NewTypedMethodsHandlerBuilder(options ...any) chioas.MethodHandlerBuilder
- type ApiError
- type ArgBuilder
- type ArgExtractor
- type BasicAuth
- type ErrorHandler
- type Headers
- type JsonResponse
- type MultiResponseMarshaler
- type PathParams
- type PostForm
- type QueryParams
- type RawQuery
- type ResponseHandler
- type ResponseMarshaler
- type Unmarshaler
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewTypedMethodsHandlerBuilder ¶
func NewTypedMethodsHandlerBuilder(options ...any) chioas.MethodHandlerBuilder
NewTypedMethodsHandlerBuilder creates a new handler for use on chioas.Definition and provides capability to have typed methods/funcs for API endpoints.
the options arg can be any of types ErrorHandler, Unmarshaler, ResponseHandler, ArgBuilder or ArgExtractor[T]
if no Unmarshaler is passed then a default JSON unmarshaler is used - and if multiple Unmarshaler are passed then only the last one is used
For a complete example, see package docs
Types ¶
type ApiError ¶
ApiError is an error interface that can be returned from typed handlers allowing the status code for the error to be set in the response
Implementations of this interface can also be used by ResponseMarshaler.Marshal and JsonResponse.Error
func NewApiError ¶
NewApiError creates a new ApiError with the specified status code and error message
If the message is an empty string, the actual message is set from the status code using http.StatusText ¶
Note: If the provided status code is less than 100 (http.StatusContinue) the status code http.StatusInternalServerError is used
func NewApiErrorf ¶
NewApiErrorf creates a new ApiError with the specified status code and error format + args
If the message is an empty string, the actual message is set from the status code using http.StatusText ¶
Note: If the provided status code is less than 100 (http.StatusContinue) the status code http.StatusInternalServerError is used
func WrapApiError ¶
WrapApiError creates a new ApiError by wrapping the error and using the provided status code
Note: If the provided error is nil then nil is returned
Note: If the provided status code is less than 100 (http.StatusContinue) the status code http.StatusInternalServerError is used
func WrapApiErrorMsg ¶
WrapApiErrorMsg creates a new ApiError by wrapping the error - using the provided status code and optionally overriding the message
Note: If the provided error is nil then nil is returned
Note: If the provided status code is less than 100 (http.StatusContinue) the status code http.StatusInternalServerError is used
type ArgBuilder ¶
type ArgBuilder interface { // IsApplicable determines whether this ArgBuilder can handle the given arg reflect.Type // // If it is applicable, this method should return true - and return readsBody true if it intends to read the request body (as only one arg can read the request body) // // The method and path are provided for information purposes IsApplicable(argType reflect.Type, method string, path string) (is bool, readsBody bool) // BuildValue builds the final arg reflect.Value that will be used to call the typed handler // // If no error is returned, then the reflect.Value returned MUST match the arg type (failure to do so will result in an error response) BuildValue(argType reflect.Type, request *http.Request, params []urit.PathVar) (reflect.Value, error) }
ArgBuilder is an interface that can be passed as an option to NewTypedMethodsHandlerBuilder, allowing support for additional typed handler arg types
func NewMultipartFormArgSupport ¶ added in v1.12.6
func NewMultipartFormArgSupport(maxMemory int64, noAutoError bool) ArgBuilder
NewMultipartFormArgSupport creates an arg type builder - for use as an option passed to NewTypedMethodsHandlerBuilder(options ...any)
By adding this as an option to NewTypedMethodsHandlerBuilder, any typed handler with an arg of type *multipart.Form will be supported
If a typed handler has an arg type of *multipart.Form but the request is not `Content-Type=multipart/form-data`, or the request body is nil (or any other error from http.Request.ParseMultipartForm) then the typed handler is not called and an error response of 400 Bad Request is served - unless noAuthError is set, in which case such errors result in a nil *multipart.Form being passed to the typed handler
type ArgExtractor ¶ added in v1.14.1
type ArgExtractor[T any] struct { // Extract is the function that extracts the arg value from the request Extract func(r *http.Request) (T, error) // ReadsBody denotes that the arg uses the request body ReadsBody bool }
ArgExtractor is a struct that can be passed as an option to NewTypedMethodsHandlerBuilder and contains a function that extracts the typed arg from the request
For example, if your API had multiple places where an 'id' path param was used - you could alias the id type...
type Id string
and then in the handler...
func DeletePerson(personId Id) { ... }
and create an ArgExtractor to get the id from the path param...
idExtractor := &ArgExtractor[Id]{ Extract: func(r *http.Request) (Id, error) { return Id(chi.URLParam(r, "id")), nil }, }
and use the ArgExtractor...
var myApiDef = chioas.Definition{ ... MethodHandlerBuilder: typed.NewTypedMethodsHandlerBuilder(idExtractor), ... }
Or, if the extractor for the given arg type never reads the request body, you can simply specify the extractor as a func - with the signature:
func(r *http.Request) (T, error)
where T is the arg type
type BasicAuth ¶ added in v1.12.8
BasicAuth is a type that can be used as a typed handler arg to receive request BasicAuth
If type *typed.BasicAuth is used as the typed handler arg, then the value will be nil if no Authorization header is present on the request or if the Authorization header is not basic auth (i.e. value does not start with "Basic ")
type ErrorHandler ¶
type ErrorHandler interface {
HandleError(writer http.ResponseWriter, request *http.Request, err error)
}
ErrorHandler is an interface that can be used to write an error to the response
an ErrorHandler can be passed as an option to NewTypedMethodsHandlerBuilder
The original *http.Request is passed so that responses can be written in the required content type (i.e. according to the `Accept` header)
type JsonResponse ¶
type JsonResponse struct { // Error is the optional error that can be returned Error error // StatusCode is the status code for the response (if less than 100 Continue then 200 OK is assumed) StatusCode int // Headers is any headers to be set on the response Headers [][2]string // Body is any payload for the response body (marshalled to JSON) Body any }
JsonResponse is a struct that can be returned from a typed handler
The response error, status code, headers and body are determined by the properties
type MultiResponseMarshaler ¶ added in v1.12.2
type MultiResponseMarshaler struct { // Error is the optional error that can be returned Error error // StatusCode is the status code for the response (if less than 100 Continue then 200 OK is assumed) StatusCode int // Headers is any headers to be set on the response (note the `Content-Type` header will be set automatically but can be overridden by these) Headers [][2]string // Body is any payload to be marshaled for the response body // // If Body is nil the status code will default 204 No Content (i.e. if StatusCode is less than 100) // // Note: It is up to you to ensure that the Body can be reliably marshalled into all json, yaml and xml - for example, map[string]any will NOT marshal into xml Body any // FallbackContentType is the content type to assume if the `Accept` header is not one of json, yaml or xml // // If this value is empty (or not one of "application/json", "application/yaml" or "application/xml") then // no fallback is used FallbackContentType string // ExcludeJson if set, prevents MultiResponseMarshaler supporting json ExcludeJson bool // ExcludeYaml if set, prevents MultiResponseMarshaler supporting yaml ExcludeYaml bool // ExcludeXml if set, prevents MultiResponseMarshaler supporting xml ExcludeXml bool }
MultiResponseMarshaler is an implementation of ResponseMarshaler that supports marshalling a response value as json, yaml or xml - according to the request `Accept` header
If the `Accept` header does not indicate json, yaml or xml then an ApiError indicating status code 406 Not Acceptable (unless a FallbackContentType is supplied)
type PathParams ¶
PathParams is a type that can be used as a typed handler arg to receive request path params
Another way to receive request path params (in order) is to use either []string or ...string (varadic) examples:
func getSomething(pathParams []string) (json.RawMessage, error) func getSomething(pathParams ..string) (json.RawMessage, error)
type PostForm ¶ added in v1.12.7
PostForm is a type that can be used as a typed handler arg to receive request PostForm values
Note: If this arg type is used for a typed handler that does not handle http methods POST, PUT or PATH - then the value will be empty (and the request body will not have been read)
type QueryParams ¶
QueryParams is a type that can be used as a typed handler arg to receive request query params
type RawQuery ¶
type RawQuery string
RawQuery is a type that can be used as a typed handler arg to receive request raw query
type ResponseHandler ¶ added in v1.16.3
type ResponseHandler interface { // WriteResponse writes a successful response // // the value and statusCode args are obtained from the return args of the typed handler WriteResponse(writer http.ResponseWriter, request *http.Request, value any, statusCode int, thisApi any) // WriteErrorResponse writes an error response // // the err arg is obtained from the error returned from the typed handler WriteErrorResponse(writer http.ResponseWriter, request *http.Request, err error, thisApi any) }
ResponseHandler is an interface that can be used to write responses
a ResponseHandler can be passed as an option to NewTypedMethodsHandlerBuilder
The API itself can also implement this interface
type ResponseMarshaler ¶
type ResponseMarshaler interface { // Marshal marshals the response for writing // // the *http.Request is passed as an arg so that the marshalling can take account of request type (i.e. `Accept` header) Marshal(request *http.Request) (data []byte, statusCode int, hdrs [][2]string, err error) }
ResponseMarshaler is an interface that can be implemented by objects returned from a typed handler
The body of the response is written by the data provided from Marshal, the response status code is also set from that returned and so are any headers
type Unmarshaler ¶
Unmarshaler is an interface that can be passed as an option to NewTypedMethodsHandlerBuilder, allowing support for unmarshalling different content types (e.g. overriding default JSON unmarshalling and/or varying the unmarshalling according to the request `Content-Type` header)
var (
MultiUnmarshaler Unmarshaler = _MultiUnmarshaler // MultiUnmarshaler is an Unmarshaler that supports unmarshalling json, yaml and xml - and can be used as an option passed to NewTypedMethodsHandlerBuilder
)