Documentation ¶
Overview ¶
Package httpin helps decoding an HTTP request to a custom struct by binding data with querystring (query params), HTTP headers, form data, JSON/XML payloads, URL path params, and file uploads (multipart/form-data).
Index ¶
- Constants
- Variables
- func Decode[T any](req *http.Request, opts ...core.Option) (*T, error)
- func DecodeTo(req *http.Request, input any, opts ...core.Option) error
- func New(inputStruct any, opts ...core.Option) (*core.Core, error)
- func NewInput(inputStruct any, opts ...core.Option) func(http.Handler) http.Handler
- func NewRequest(method, url string, input any, opts ...core.Option) (*http.Request, error)
- func NewRequestWithContext(ctx context.Context, method, url string, input any, opts ...core.Option) (*http.Request, error)
- type File
Constants ¶
const ( // Input is the key to get the input object from Request.Context() injected by httpin. e.g. // // input := r.Context().Value(httpin.Input).(*InputStruct) Input contextKey = iota )
Variables ¶
var Option coreOptions = coreOptions{ WithErrorHandler: core.WithErrorHandler, WithMaxMemory: core.WithMaxMemory, WithNestedDirectivesEnabled: core.WithNestedDirectivesEnabled, }
Option is a collection of options for creating a Core instance.
Functions ¶
func Decode ¶ added in v0.11.0
Decode decodes an HTTP request to an instance of T and returns its pointer (*T). T must be a struct type. For example:
if user, err := Decode[User](req); err != nil { ... } // now user is a *User instance, which has been populated with data from the request.
func DecodeTo ¶ added in v0.18.0
DecodeTo decodes an HTTP request and populates input with data from the HTTP request. The input must be a pointer to a struct instance. For example:
input := &InputStruct{} if err := DecodeTo(req, input); err != nil { ... }
input is now populated with data from the request.
func New ¶
New calls core.New to create a new Core instance. Which is responsible for both:
- decoding an HTTP request to an instance of the inputStruct;
- and encoding an instance of the inputStruct to an HTTP request.
Note that the Core instance is bound to the given specific type, it will not work for other types. If you want to decode/encode other types, you need to create another Core instance. Or directly use the following functions, which are just shortcuts of Core's methods, so you don't need to create a Core instance:
- httpin.Decode(): decode an HTTP request to an instance of the inputStruct.
- httpin.NewRequest() to encode an instance of the inputStruct to an HTTP request.
For best practice, we would recommend using httpin.NewInput() to create an HTTP middleware for a specific input type. The middleware can be bound to an API, chained with other middlewares, and also reused in other APIs. You even don't need to call the Deocde() method explicitly, the middleware will do it for you and put the decoded instance to the request's context.
func NewInput ¶
NewInput creates an HTTP middleware handler. Which is a function that takes in an http.Handler and returns another http.Handler.
The middleware created by NewInput is to add the decoding function to an existing http.Handler. This functionality will decode the HTTP request into a struct instance and put its pointer to the request's context. So that the next hop can get the decoded struct instance from the request's context.
We recommend using https://github.com/justinas/alice to chain your middlewares. If you're using some popular web frameworks, they may have already provided a middleware chaining mechanism.
For example:
type ListUsersRequest struct { Page int `in:"query=page,page_index,index"` PerPage int `in:"query=per_page,page_size"` } func ListUsersHandler(rw http.ResponseWriter, r *http.Request) { input := r.Context().Value(httpin.Input).(*ListUsersRequest) // ... } func init() { http.Handle("/users", alice.New(httpin.NewInput(&ListUsersRequest{})).ThenFunc(ListUsersHandler)) }
func NewRequest ¶ added in v0.15.0
NewRequest wraps NewRequestWithContext using context.Background(), see NewRequestWithContext.
func NewRequestWithContext ¶ added in v0.15.0
func NewRequestWithContext(ctx context.Context, method, url string, input any, opts ...core.Option) (*http.Request, error)
NewRequestWithContext turns the given input into an HTTP request. The input must be a struct instance. And its fields' "in" tags define how to bind the data from the struct to the HTTP request. Use it as the replacement of http.NewRequest().
addUserPayload := &AddUserRequest{...} addUserRequest, err := NewRequestWithContext(context.Background(), "GET", "http://example.com", addUserPayload) http.DefaultClient.Do(addUserRequest)
Types ¶
type File ¶ added in v0.7.0
File is the builtin type of httpin to manupulate file uploads. On the server side, it is used to represent a file in a multipart/form-data request. On the client side, it is used to represent a file to be uploaded.
func UploadFile ¶ added in v0.15.0
UploadFile is a helper function to create a File instance from a file path. It is useful when you want to upload a file from the local file system.
func UploadStream ¶ added in v0.15.0
func UploadStream(r io.ReadCloser) *File
UploadStream is a helper function to create a File instance from a io.Reader. It is useful when you want to upload a file from a stream.