Documentation
¶
Overview ¶
Package request provides HTTP request decoding and validation helpers shared across handlers: JSON body decoding with size limits and error mapping (json.go), localizable user-facing messages (messages.go), and query/URL- parameter validation (validate.go).
Index ¶
- func JSON(w http.ResponseWriter, r *http.Request, data any) error
- func JSONOptional(w http.ResponseWriter, r *http.Request, data any) error
- func JSONWithLimit(w http.ResponseWriter, r *http.Request, data any, maxBytes int64) error
- type Decoder
- func (d *Decoder) JSON(w http.ResponseWriter, r *http.Request, data any) error
- func (d *Decoder) JSONOptional(w http.ResponseWriter, r *http.Request, data any) error
- func (d *Decoder) JSONWithLimit(w http.ResponseWriter, r *http.Request, data any, maxBytes int64) error
- func (d *Decoder) NewValidator() *Validator
- type FieldErrors
- type Messages
- type Option
- type Validator
- func (v *Validator) AddError(field, message string)
- func (v *Validator) BoolQuery(r *http.Request, param string) *bool
- func (v *Validator) DateQuery(r *http.Request, param string) *time.Time
- func (v *Validator) Enum(param, value string, allowed []string) string
- func (v *Validator) Errors() FieldErrors
- func (v *Validator) HasErrors() bool
- func (v *Validator) Int64Param(r *http.Request, param string) int64
- func (v *Validator) Int64Query(r *http.Request, param string) *int64
- func (v *Validator) Int64sQuery(r *http.Request, param string) []int64
- func (v *Validator) IntQuery(r *http.Request, param string, defaultVal int) int
- func (v *Validator) MaxInt(param string, val, max int) int
- func (v *Validator) Messages() Messages
- func (v *Validator) PublicIDParam(r *http.Request, param string) string
- func (v *Validator) TimeQuery(r *http.Request, param string) *time.Time
- func (v *Validator) UUIDParam(r *http.Request, param string) uuid.UUID
- func (v *Validator) UUIDQuery(r *http.Request, param string) *uuid.UUID
- func (v *Validator) WriteErrors(w http.ResponseWriter, r *http.Request)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func JSON ¶
JSON decodes the request body into data and returns nil on success. The body is limited to defaultMaxBytes. On failure it writes a 400/413 JSON response directly and returns the error, so the caller only needs:
if err := request.JSON(w, r, &req); err != nil {
return
}
func JSONOptional ¶ added in v0.4.0
JSONOptional decodes the request body into data like JSON, but treats an empty body as success instead of an error: it writes nothing to w, returns nil, and leaves data exactly as the caller passed it — it is not reset, so a destination reused across requests keeps its previous values. Pass a fresh (zero) value to get defaults for an absent body. This is for endpoints where the body itself is optional — a PATCH with no fields to update, for example — as opposed to a required body that happens to be malformed, which is still a 400 exactly like JSON.
func JSONWithLimit ¶
JSONWithLimit decodes the request body into data with a caller-supplied byte limit. It behaves like JSON but lets callers override the default limit — for example, a bulk-import endpoint that legitimately accepts larger bodies. On failure it writes a 400/413 JSON response directly and returns the error.
Types ¶
type Decoder ¶ added in v0.4.0
type Decoder struct {
// contains filtered or unexported fields
}
Decoder decodes JSON request bodies and constructs Validators, both using a fixed set of Messages. It is immutable once returned by New — WithMessages options only run during construction — so a single Decoder value is safe to share and call concurrently from any number of handlers/goroutines.
Build it with New. A Decoder that did not come from New — a zero value or a nil pointer — is still safe to use: it falls back to DefaultMessages instead of calling a nil message func.
func New ¶ added in v0.4.0
New creates a Decoder starting from DefaultMessages, applying opts in order. With no options, the returned Decoder behaves identically to the package-level JSON/JSONWithLimit/JSONOptional/NewValidator functions.
func (*Decoder) JSON ¶ added in v0.4.0
JSON decodes the request body into data using d's Messages. See the package-level JSON for behavior.
func (*Decoder) JSONOptional ¶ added in v0.4.0
JSONOptional decodes the request body into data using d's Messages, treating an empty body as success. See the package-level JSONOptional for behavior.
func (*Decoder) JSONWithLimit ¶ added in v0.4.0
func (d *Decoder) JSONWithLimit(w http.ResponseWriter, r *http.Request, data any, maxBytes int64) error
JSONWithLimit decodes the request body into data using d's Messages, with a caller-supplied byte limit. See the package-level JSONWithLimit for behavior.
func (*Decoder) NewValidator ¶ added in v0.4.0
NewValidator creates a ready-to-use Validator that records errors using d's configured Messages.
type FieldErrors ¶
FieldErrors maps field names to human-readable error messages.
type Messages ¶ added in v0.4.0
type Messages struct {
// MalformedJSON is used on HTTP 400 when the request body is not valid
// JSON (a syntax error). offset is the byte offset from
// encoding/json.SyntaxError where the parser gave up.
MalformedJSON func(offset int64) string
// WrongType is used on HTTP 400 when a field's JSON value does not match
// its Go struct field's type. expected is
// encoding/json.UnmarshalTypeError.Type.String().
WrongType func(field, expected string) string
// BodyTooLarge is used on HTTP 413 when the request body exceeds the
// configured byte limit (defaultMaxBytes for JSON, or the caller-supplied
// limit for JSONWithLimit). limitMB is that limit expressed in megabytes.
BodyTooLarge func(limitMB float64) string
// EmptyBody is used on HTTP 400 when JSON or JSONWithLimit receives an
// empty request body. JSONOptional treats an empty body as success
// instead, so this message never applies there.
EmptyBody string
// UnknownField is used on HTTP 400 when the body contains a field not
// present in the destination struct (DisallowUnknownFields is always
// on). field is the raw quoted field name as encoding/json reports it,
// e.g. `"bogus"`.
UnknownField func(field string) string
// InvalidBody is used on HTTP 400 as the fallback for a decode error that
// does not match any of the more specific cases above.
InvalidBody string
// Required is used by Validator methods that reject a missing/empty
// value (UUIDParam, Int64Param, PublicIDParam), as part of a 400
// validation-error response written by WriteErrors.
Required func(field string) string
// InvalidUUID is used by Validator.UUIDParam and Validator.UUIDQuery when
// the value fails uuid.Parse.
InvalidUUID func(field string) string
// NotInteger is used by Validator.IntQuery when the value fails
// strconv.Atoi.
NotInteger func(field string) string
// Negative is used by Validator.IntQuery when the parsed value is below
// zero.
Negative func(field string) string
// InvalidRFC3339 is used by Validator.TimeQuery when the value fails
// time.Parse(time.RFC3339, ...).
InvalidRFC3339 func(field string) string
// InvalidISODate is used by Validator.DateQuery when the value fails
// time.Parse("2006-01-02", ...).
InvalidISODate func(field string) string
// InvalidInteger is used by Validator.Int64Param when the value fails
// strconv.ParseInt.
InvalidInteger func(field string) string
// NotAllowed is used by Validator.Enum when a non-empty value is not one
// of the allowed options.
NotAllowed func(field string) string
// InvalidPublicID is used by Validator.PublicIDParam when the value is
// neither a valid UUID nor a valid ULID.
InvalidPublicID func(field string) string
// InvalidIntegerList is used by Validator.Int64sQuery when any
// comma-separated entry fails strconv.ParseInt.
InvalidIntegerList func(field string) string
// InvalidBoolean is used by Validator.BoolQuery when the value fails
// strconv.ParseBool.
InvalidBoolean func(field string) string
// InvalidDecimal is not read by anything in this package directly. It
// exists so a decimal-parsing helper package outside request (for
// example, decimalx) can report a validation failure with wording that
// stays consistent with the rest of a Validator's messages, via
// Validator.Messages().InvalidDecimal.
InvalidDecimal func(field string) string
}
Messages holds every user-facing string this package can return, split into two groups: the decode-path messages a Decoder writes into a JSON error response (json.go), and the validation messages a Validator records per field (validate.go).
A library must not bake user-facing copy in one language: what reads as a helpful English error to one deployment is the wrong language for another. DefaultMessages returns neutral English defaults; each consuming application configures its own copy once, via New(WithMessages(...)), and every handler built from that Decoder or its Validators uses it.
There is deliberately no message for Validator.MaxInt: it only clamps a value to a maximum and never records a validation error, in this package and in every known fork of it. Adding a message field nothing would ever read is dead API.
func DefaultMessages ¶ added in v0.4.0
func DefaultMessages() Messages
DefaultMessages returns the neutral English defaults used when a Decoder is built with no WithMessages option. These are the exact texts this package has always returned, so building a Decoder via New() with no options produces byte-identical responses to the package-level functions.
type Option ¶ added in v0.4.0
type Option func(*Decoder)
Option customizes a Decoder built with New.
func WithMessages ¶ added in v0.4.0
WithMessages overrides the default user-facing messages. Any field left as its zero value (nil func, or "" for a plain string) keeps the DefaultMessages value, so a caller only needs to set the fields it wants to localize.
type Validator ¶
type Validator struct {
// contains filtered or unexported fields
}
Validator accumulates validation errors across multiple fields so a handler can validate every input before responding, instead of failing on the first bad field and forcing the client into a fix-one-error-per-request loop.
func NewValidator ¶
func NewValidator() *Validator
NewValidator creates a ready-to-use Validator using DefaultMessages. Use Decoder.NewValidator (built via New and WithMessages) to localize the messages a Validator records.
func (*Validator) AddError ¶ added in v0.4.0
AddError records message as the error for field, overwriting any previous error recorded for that same field. It is the supported way for a consumer embedding Validator in its own parsers to report a validation failure through the same Validator instance, alongside this package's own checks.
func (*Validator) BoolQuery ¶ added in v0.5.0
BoolQuery extracts and validates a boolean query parameter. Returns nil if the parameter is absent or empty, with no error recorded. It accepts exactly what strconv.ParseBool accepts (1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False); anything else records an InvalidBoolean error and returns nil.
func (*Validator) DateQuery ¶
DateQuery extracts and validates a date query parameter in ISO format (2006-01-02). Returns nil if the parameter is absent.
func (*Validator) Enum ¶
Enum validates that a string value is one of the allowed options. Returns the value as-is if empty (optional field) or if it matches.
func (*Validator) Errors ¶
func (v *Validator) Errors() FieldErrors
Errors returns the accumulated field errors. It returns the live map, not a copy, so mutating it mutates the Validator's state. AddError is the supported way to add entries from outside this package — for example, a consuming application wrapping Validator with its own query-parameter parsers (an Int64Query, BoolQuery, or DecimalQuery that stays in that application rather than this package).
func (*Validator) Int64Param ¶
Int64Param extracts and validates a chi URL parameter as an int64. Returns 0 if validation fails.
func (*Validator) Int64Query ¶ added in v0.5.0
Int64Query extracts and validates an int64 query parameter. Returns nil if the parameter is absent or empty, with no error recorded — the caller decides what an absent value means (unlike IntQuery, which takes a default). A value present but not a base-10 int64 (strconv.ParseInt(raw, 10, 64)) records an InvalidInteger error and returns nil.
func (*Validator) Int64sQuery ¶
Int64sQuery extracts a comma-separated list of int64 values from a query parameter. Returns nil if the parameter is absent.
func (*Validator) IntQuery ¶
IntQuery extracts and validates an integer query parameter with a default value. Returns the default if the parameter is absent.
func (*Validator) Messages ¶ added in v0.5.0
Messages returns the effective Messages this Validator records field errors with: DefaultMessages merged with whatever WithMessages options built the Decoder that created it (see Decoder.NewValidator).
It exists so a helper package that stays outside request — for example, decimalx, which must not be imported here because request must not depend on shopspring/decimal — can still record an error using this Validator's own configured wording instead of hardcoding English text:
v.AddError(param, v.Messages().InvalidDecimal(param))
func (*Validator) PublicIDParam ¶
PublicIDParam extracts and validates a chi URL parameter as a UUID or ULID. Returns the raw string unchanged. Returns "" if validation fails.
func (*Validator) TimeQuery ¶
TimeQuery extracts and validates an RFC3339 time query parameter. Returns nil if the parameter is absent.
func (*Validator) UUIDParam ¶
UUIDParam extracts and validates a chi URL parameter as a UUID. Returns uuid.Nil if validation fails.
func (*Validator) UUIDQuery ¶
UUIDQuery extracts and validates a query parameter as a UUID. Returns nil if the parameter is absent.
func (*Validator) WriteErrors ¶
func (v *Validator) WriteErrors(w http.ResponseWriter, r *http.Request)
WriteErrors sends a 400 response with the accumulated field errors.