router

package
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 6, 2024 License: MIT Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	LogLevelError = utils.Error
	LogLevelWarn  = utils.Warn
	LogLevelInfo  = utils.Info
	LogLevelOff   = utils.Off
)
View Source
const (
	// PropagateError propagate validation errors to OpenAPIRouter.AsHandler return values and print them to the log.
	// This is also the initial Behaviour value if not set to anything else.
	PropagateError = Behaviour(utils.Error)
	// PrintWarning print validation errors as warning to the log without propagating the error to OpenAPIRouter.AsHandler return values
	PrintWarning = Behaviour(utils.Warn)
	// Ignore do nothing if the validation fails.
	// A validation failure won't get printed to the logs and an error won't get propagate to OpenAPIRouter.AsHandler return values
	Ignore = Behaviour(utils.Off)
)

Variables

View Source
var (
	UnsupportedRequestContentTypeErr  = errors.New("unsupported request content type for operation")
	UnsupportedResponseContentTypeErr = errors.New("unsupported response content type for operation")
	UnsupportedResponseStatusErr      = errors.New("unsupported response status for operation")
)

Runtime errors causes

View Source
var (

	// ErrInvalidUUID is returned when the uuid format validation fails.
	ErrInvalidUUID = errors.New("invalid uuid")
)
View Source
var ErrSpecValidation = errors.New("spec validation failed")

Functions

func DefaultOptionsHandler added in v1.6.0

func DefaultOptionsHandler(writer http.ResponseWriter, _ *http.Request)

DefaultOptionsHandler This handler is the default OPTIONS handler provided when using DefaultOptions. It will respond to each OPTIONS request with an "Allow" header that will include all the methods that are defined for the path and respond with 204 status.

Types

type BadRequestErr

type BadRequestErr struct {
	Err     error
	In      In
	Context *Context
}

BadRequestErr is the error returned when there is an error binding the request. You can handle this request using an ErrorHandler middleware to return a custom HTTP response.

func (BadRequestErr) Error

func (e BadRequestErr) Error() string

func (BadRequestErr) Is

func (e BadRequestErr) Is(err error) bool

func (BadRequestErr) Unwrap

func (e BadRequestErr) Unwrap() error

type Behaviour

type Behaviour utils.LogLevel

Behaviour defines a possible behaviour for a validation error. Possible values are PropagateError, PrintWarning and Ignore.

  • PropagateError - Cause call to OpenAPIRouter.AsHandler to return an error if the validation fails and failure reason is logged with error level.
  • PrintWarning - if the validation fails the failure reason will get logged with warning level. The error won't propagate to OpenAPIRouter.AsHandler return values
  • Ignore - do nothing if the validation fails. don't print anything to the logs and don't propagate the error to OpenAPIRouter.AsHandler return values

By default, Behaviour are initialized to PropagateError as it is essentially Behaviour zero value.

func (Behaviour) MarshalText

func (b Behaviour) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (*Behaviour) UnmarshalText

func (b *Behaviour) UnmarshalText(data []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type BoundHandlerFunc

type BoundHandlerFunc func(*Context) (RawResponse, error)

BoundHandlerFunc is an untyped wrapper to HandlerFunc that bound internally calls to request binding, response binding and propagate next handler in the Context.

type ContentType

type ContentType interface {
	Mime() string
	Encode(any) ([]byte, error)
	Decode([]byte, any) error
	ValidateTypeSchema(utils.Logger, utils.LogLevel, reflect.Type, openapi3.Schema) error
}

type ContentTypes

type ContentTypes map[string]ContentType

func DefaultContentTypes

func DefaultContentTypes() ContentTypes

type Context

type Context struct {
	Operation   SpecOperation
	Writer      http.ResponseWriter
	Request     *http.Request
	Params      *httprouter.Params
	RawResponse *RawResponse
	NextFunc    BoundHandlerFunc
}

Context carries the original http.Request and http.ResponseWriter and additional important parameters through the handlers chain.

func (*Context) Next

func (c *Context) Next() (RawResponse, error)

type Group

type Group interface {
	// Use middlewares on the root handler
	Use(...Handler) Group
	// WithGroup defines a virtual group that allow defining middlewares for group of routes more easily
	WithGroup(Group) Group
	// WithOperation attaches a MiddlewareHandler for an operation ID string on the OpenAPISpec
	WithOperation(string, Handler, ...Handler) Group
	// contains filtered or unexported methods
}

func NewGroup

func NewGroup() Group

type Handler

type Handler interface {
	// contains filtered or unexported methods
}

Handler described the HandlerFunc in a non parametrized way. The router "magic" of being a collection of many HandlerFunc with each having a different generic parameter is possible by describing each HandlerFunc with this unified Handler interface. Eventually a Handler is anything that can report its requestTypes, handlerResponses, sourcePosition and can become a BoundHandlerFunc by calling the handlerFactory method.

func NewHandler

func NewHandler[B, P, Q, R any](h HandlerFunc[B, P, Q, R]) Handler

func RawHandler

func RawHandler(f func(c *Context) error) Handler

RawHandler adds a handler that doesn't define any type information.

type HandlerFunc

type HandlerFunc[B, P, Q, R any] func(*Context, Request[B, P, Q]) (Response[R], error)

HandlerFunc is the typed handler that declare explicitly all types of request and responses. Check the repo examples for seeing how the HandlerFunc can be used to define Handler for operations and middlewares.

func ErrorHandler

func ErrorHandler[R any](errHandler func(c *Context, err error) (Response[R], error)) HandlerFunc[utils.Nil, utils.Nil, utils.Nil, R]

ErrorHandler allows providing a handler function that can handle errors occurred in the handlers chain. This type of handler is particularly useful for handling BadRequestErr caused by a request binding errors and translate it to an HTTP response.

type In

type In int

In is a location of a request binding error

const (
	InBody In = iota
	InPathParams
	InQueryParams
)

func (In) String added in v1.0.7

func (in In) String() string

type JSONContentType

type JSONContentType struct{}

func (JSONContentType) Decode

func (t JSONContentType) Decode(data []byte, value any) error

func (JSONContentType) Encode

func (t JSONContentType) Encode(value any) ([]byte, error)

func (JSONContentType) Mime

func (t JSONContentType) Mime() string

func (JSONContentType) ValidateTypeSchema added in v1.0.11

func (t JSONContentType) ValidateTypeSchema(
	logger utils.Logger, level utils.LogLevel, goType reflect.Type, schema openapi3.Schema) error

type LogLevel added in v1.2.0

type LogLevel = utils.LogLevel

type MultiType added in v1.2.0

type MultiType[T any] utils.MultiType[T]

type Nil

type Nil = utils.Nil

type OctetStreamContentType

type OctetStreamContentType struct{}

func (OctetStreamContentType) Decode

func (t OctetStreamContentType) Decode(data []byte, value any) error

func (OctetStreamContentType) Encode

func (t OctetStreamContentType) Encode(value any) ([]byte, error)

func (OctetStreamContentType) Mime

func (t OctetStreamContentType) Mime() string

func (OctetStreamContentType) ValidateTypeSchema added in v1.0.11

func (t OctetStreamContentType) ValidateTypeSchema(
	logger utils.Logger, level utils.LogLevel, goType reflect.Type, schema openapi3.Schema) error

type OpenAPIRouter

type OpenAPIRouter interface {
	// Use middlewares on the root handler
	Use(...Handler) OpenAPIRouter
	// WithGroup defines a virtual group that allow defining middlewares for group of routes more easily
	WithGroup(Group) OpenAPIRouter
	// WithOperation attaches an MiddlewareHandler for an operation ID string on the OpenAPISpec
	WithOperation(string, Handler, ...Handler) OpenAPIRouter

	// WithContentType add to the router implementation for encoding additional content types.
	//
	// By default, the OpenAPIRouter supports the ContentTypes defined by DefaultContentTypes.
	//
	// An implementation of ContentType add support for additional content types by implementing serialization and
	// deserialization.
	WithContentType(ContentType) OpenAPIRouter

	// AsHandler validates the validity of the specified implementation with the registered OpenAPISpec.
	//
	// Returns a http.Handler and nil error if all checks passed correctly
	//
	// The returned handler can be used easily with any go http web framework as it is implementing the builtin
	// http.Handler interface.
	AsHandler() (http.Handler, error)

	// Spec returns the OpenAPI spec used by the router.
	Spec() OpenAPISpec
}

func NewOpenAPIRouter

func NewOpenAPIRouter(spec OpenAPISpec) OpenAPIRouter

NewOpenAPIRouter creates new OpenAPIRouter router with the provided OpenAPISpec.

The OpenAPISpec can be obtained by calling any of the OpenAPISpec loading functions:

  • NewSpecFromData - Init an OpenAPISpec from bytes represent the spec JSON or YAML.
  • NewSpecFromFile - Init an OpenAPISpec from a path to a spec file.
  • NewSpec - Create an empty spec object that can be initialized programmatically.

This function also initialize OpenAPIRouter with the DefaultOptions, you can also initialize the router with custom Options using the NewOpenAPIRouterWithOptions function instead.

func NewOpenAPIRouterWithOptions

func NewOpenAPIRouterWithOptions(spec OpenAPISpec, options Options) OpenAPIRouter

NewOpenAPIRouterWithOptions creates new OpenAPIRouter router with the provided OpenAPISpec and custom Options.

OpenAPISpec can be obtained by calling any of the OpenAPISpec loading functions:

  • NewSpecFromData - Init an OpenAPISpec from bytes represent the spec JSON or YAML.
  • NewSpecFromFile - Init an OpenAPISpec from a path to a spec file.
  • NewSpec - Create an empty spec object that can be initialized programmatically.

This function also receives an Options object that allow customizing the default behaviour of the router. Check the Options documentation for more details.

If you want to use the OpenAPIRouter with the DefaultOptions, you can use the shorter NewOpenAPIRouter function instead.

type OpenAPISpec

type OpenAPISpec openapi3.T

func NewSpec

func NewSpec() OpenAPISpec

func NewSpecFromData

func NewSpecFromData(data []byte) (OpenAPISpec, error)

func NewSpecFromFile

func NewSpecFromFile(path string) (OpenAPISpec, error)

func (*OpenAPISpec) Operations added in v1.0.12

func (s *OpenAPISpec) Operations() map[string]SpecOperation

Operations returns all operations declared in the spec as a map of operation ID to SpecOperation.

type OperationValidationOptions

type OperationValidationOptions struct {
	// ValidatePathParams determines validation of operation request body.
	ValidateRequestBody Behaviour `json:"validateRequestBody,omitempty"`

	// ValidatePathParams determines validation of operation path params.
	ValidatePathParams Behaviour `json:"validatePathParams,omitempty"`

	// HandleAllPathParams describes the behaviour when not every path params defined in the spec is handled at least once in the handlers chain
	HandleAllPathParams Behaviour `json:"handleAllPathParams,omitempty"`

	// ValidatePathParams determines validation of operation query params.
	ValidateQueryParams Behaviour `json:"validateQueryParams,omitempty"`

	// HandleAllQueryParams describes the behaviour when not every query params defined in the spec is handled at least once in the handlers chain
	HandleAllQueryParams Behaviour `json:"handleAllQueryParams,omitempty"`

	// ValidatePathParams determines validation of operation responses.
	ValidateResponses Behaviour `json:"validateResponses,omitempty"`

	// HandleAllOperationResponses describes the behaviour when not every response defined in the spec is handled at least once in the handlers chain
	HandleAllOperationResponses Behaviour `json:"handleAllOperationResponses,omitempty"`

	// ContentTypesToSkipRuntimeValidation defines a list of content types that are skipped when validating operation request body at runtime.
	ContentTypesToSkipRuntimeValidation []string `json:"contentTypesToSkipRuntimeValidation,omitempty"`

	// RuntimeValidateResponses defines the behaviour when validating operation response body at runtime. Printing a warning to
	// the log by default. It is recommended to turn this option to Ignore in production as it can impact performance for large
	// responses, and to be used in development and testing environments.
	RuntimeValidateResponses Behaviour `json:"runtimeValidateResponses,omitempty"`
}

OperationValidationOptions defines options to control operation validations

type Options

type Options struct {

	// When RecoverOnPanic is set to true the handlers chain provide a default recover behaviour that return status 500.
	// This feature is available and turned on by default to prevent the server from crashing when an internal panic
	// occurs in the handler chain.
	// This is a fundamental requirement of a web server to support availability.
	// While being fundamental, the default behaviour can't conform to your spec out of the box.
	// To be able to better control the behaviour during panic and the structure of the response returned to be
	// compatible with the spec it's recommended to implement it as a handler and in this case the default recover
	// behaviour can be turned off.
	RecoverOnPanic bool `json:"recoverOnPanic,omitempty"`

	// LogLevel defines what log levels should be printed to LogOutput.
	// By default, LogLevel is set to utils.Info to print all info to the log.
	// The router prints to the log only during initialization to show validation errors, warnings and useful info.
	// No printing is done after initialization.
	LogLevel LogLevel `json:"logLevel,omitempty"`

	// LogOutput defines where to write the outputs too.
	// By default, it is set to write to os.Stderr.
	// You can provide your own writer to be able to read the validation errors programmatically or to write them to
	// different destination.
	// The router prints to the log only during initialization to show validation errors, warnings and useful info.
	// No printing is done after initialization.
	LogOutput io.Writer `json:"-"`

	// OperationValidations allow defining validation for specific operations using a map of operation id to an
	// operationValidationOptions structure.
	// This option is used only to override the default operation validations options defined ny the
	// DefaultOperationValidation option.
	OperationValidations map[string]OperationValidationOptions `json:"operationValidations,omitempty"`

	// DefaultOperationValidation defines the default validations run for every operation.
	// By default, if not set the default behaviour is strict and consider any validation error to fail the entire
	// router validations.
	DefaultOperationValidation OperationValidationOptions `json:"defaultOperationValidation,omitempty"`

	// The router validates that every operation defined in the spec has an implementation.
	// MustHandleAllOperations defines the behaviour when this validation fails.
	// By default, it is set to utils.Error to propagate the error.
	// If your implementation is still in progress, and you would like to ignore unimplemented operations you can set
	// this option to utils.Warn or turn it off with utils.Off.
	MustHandleAllOperations Behaviour `json:"mustHandleAllOperations,omitempty"`

	// The router validates that every content type define in the spec has an implementation.
	// HandleAllContentTypes defines the behaviour when this validation fails.
	// By default, it is set to utils.Error to propagate the error.
	// Content types defined in the spec in operation request body and responses.
	// If your spec defines some content types that are not supported by the default router content types you can add
	// your own implementation.
	// Content type implementation is basically an implementation of ContentType interface add with
	// OpenAPIRouter.WithContentType to define serialization and deserialization behaviour.
	HandleAllContentTypes Behaviour `json:"handleAllContentTypes,omitempty"`

	// ExcludeOperations defined an array of operations that are defined in the spec but are excluded from the implementation.
	// One use for this option is when your spec defines the entire API of your app but the implementation is spread to multiple microservices.
	// With this option you can define list of operations that are to be implemented by other microservices.
	ExcludeOperations []string

	// OptionsHandler defines a handler that is called for every OPTIONS request of any path that is defined in the spec.
	// This handler allows you to define a response for OPTIONS preflight requests and control the allowed methods or set CORS headers.
	// The handler will receive the allowed methods in the `Allow` header based on the spec.
	// Set to nil to disable the automatic handling of OPTIONS requests.
	OptionsHandler http.Handler `json:"-"`
}

Options defines the behaviour of the OpenAPI router

func DefaultOptions

func DefaultOptions() Options

DefaultOptions returns the default OpenAPI Router Options. For loading different options it is recommended to start from the default Options as the baseline and modify the specific options needed. To init the router with custom Options you can use NewOpenAPIRouterWithOptions.

type PlainTextContentType

type PlainTextContentType struct{}

func (PlainTextContentType) Decode

func (t PlainTextContentType) Decode(data []byte, value any) error

func (PlainTextContentType) Encode

func (t PlainTextContentType) Encode(value any) ([]byte, error)

func (PlainTextContentType) Mime

func (t PlainTextContentType) Mime() string

func (PlainTextContentType) ValidateTypeSchema added in v1.0.11

func (t PlainTextContentType) ValidateTypeSchema(
	logger utils.Logger, level utils.LogLevel, goType reflect.Type, schema openapi3.Schema) error

type RawResponse

type RawResponse struct {
	// Status written with WriteHeader
	Status int
	// ContentType is the content type used to write the response
	ContentType string
	// buffered Body bytes written by calls to Write
	Body []byte
	// response Headers
	Headers http.Header
}

type Request

type Request[B, P, Q any] struct {
	Body        B
	PathParams  P
	QueryParams Q
	Headers     http.Header
}

type Response

type Response[R any] struct {
	// contains filtered or unexported fields
}

func Error

func Error[R any](err error) (Response[R], error)

Error is a helper function for constructing a HandlerFunc error response.

func Send

func Send[R any](response R, headers ...http.Header) Response[R]

Send constructs a new Response.

func SendBytes

func SendBytes[R any](response R, headers ...http.Header) Response[R]

SendBytes constructs a new Response with an "application/octet-stream" content-type.

func SendJSON

func SendJSON[R any](response R, headers ...http.Header) Response[R]

SendJSON constructs a new Response with an "application/json" content-type.

func SendOK

func SendOK[R any](response R, headers ...http.Header) Response[R]

SendOK constructs a new Response with an OK 200 status code.

func SendOKBytes

func SendOKBytes[R any](response R, headers ...http.Header) Response[R]

SendOKBytes constructs a new Response with an OK 200 status code and with an "application/octet-stream" content-type.

func SendOKJSON

func SendOKJSON[R any](response R, headers ...http.Header) Response[R]

SendOKJSON constructs a new Response with an OK 200 status code and with an "application/json" content-type.

func SendOKText

func SendOKText[R any](response R, headers ...http.Header) Response[R]

SendOKText constructs a new Response with an OK 200 status code and with a "plain/text" content-type.

func SendText

func SendText[R any](response R, headers ...http.Header) Response[R]

SendText constructs a new Response with a "plain/text" content-type.

func (Response[R]) AddHeader

func (r Response[R]) AddHeader(key, value string) Response[R]

AddHeader add a response header. It appends to any existing values associated with key.

func (Response[R]) ContentType

func (r Response[R]) ContentType(contentType string) Response[R]

ContentType set the response content type.

func (Response[R]) SetHeader

func (r Response[R]) SetHeader(key, value string) Response[R]

SetHeader set a response header. It replaces any existing values associated with key

func (Response[R]) Status

func (r Response[R]) Status(status int) Response[R]

Status set the response status code.

type SchemaValidationOptions

type SchemaValidationOptions struct {
	// NoEmptyInterface defines the behaviour when a schema is validated with an empty interface (any) type.
	NoEmptyInterface Behaviour `json:"noEmptyInterface,omitempty"`

	// NoStringAnyMapForObjectsSchema defines the behaviour when an object schema is validated with a string to empty interface map type (map[string]any).
	NoStringAnyMapForObjectsSchema Behaviour `json:"noStringAnyMapForObjectsSchema,omitempty"`
}

SchemaValidationOptions defines options to control schema validations

type SpecOperation

type SpecOperation struct {
	Path   string
	Method string
	*openapi3.Operation
}

SpecOperation represent the operation information described in the spec with path and method information.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL