request

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2026 License: MIT Imports: 12 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func JSON

func JSON(w http.ResponseWriter, r *http.Request, data any) error

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

func JSONOptional(w http.ResponseWriter, r *http.Request, data any) error

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

func JSONWithLimit(w http.ResponseWriter, r *http.Request, data any, maxBytes int64) error

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

func New(opts ...Option) *Decoder

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

func (d *Decoder) JSON(w http.ResponseWriter, r *http.Request, data any) error

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

func (d *Decoder) JSONOptional(w http.ResponseWriter, r *http.Request, data any) error

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

func (d *Decoder) NewValidator() *Validator

NewValidator creates a ready-to-use Validator that records errors using d's configured Messages.

type FieldErrors

type FieldErrors map[string]string

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

func WithMessages(m Messages) Option

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

func (v *Validator) AddError(field, message string)

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

func (v *Validator) BoolQuery(r *http.Request, param string) *bool

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

func (v *Validator) DateQuery(r *http.Request, param string) *time.Time

DateQuery extracts and validates a date query parameter in ISO format (2006-01-02). Returns nil if the parameter is absent.

func (*Validator) Enum

func (v *Validator) Enum(param, value string, allowed []string) string

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) HasErrors

func (v *Validator) HasErrors() bool

HasErrors reports whether any validation errors have been recorded.

func (*Validator) Int64Param

func (v *Validator) Int64Param(r *http.Request, param string) int64

Int64Param extracts and validates a chi URL parameter as an int64. Returns 0 if validation fails.

func (*Validator) Int64Query added in v0.5.0

func (v *Validator) Int64Query(r *http.Request, param string) *int64

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

func (v *Validator) Int64sQuery(r *http.Request, param string) []int64

Int64sQuery extracts a comma-separated list of int64 values from a query parameter. Returns nil if the parameter is absent.

func (*Validator) IntQuery

func (v *Validator) IntQuery(r *http.Request, param string, defaultVal int) int

IntQuery extracts and validates an integer query parameter with a default value. Returns the default if the parameter is absent.

func (*Validator) MaxInt

func (v *Validator) MaxInt(param string, val, max int) int

MaxInt clamps a value to the given maximum.

func (*Validator) Messages added in v0.5.0

func (v *Validator) Messages() Messages

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

func (v *Validator) PublicIDParam(r *http.Request, param string) string

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

func (v *Validator) TimeQuery(r *http.Request, param string) *time.Time

TimeQuery extracts and validates an RFC3339 time query parameter. Returns nil if the parameter is absent.

func (*Validator) UUIDParam

func (v *Validator) UUIDParam(r *http.Request, param string) uuid.UUID

UUIDParam extracts and validates a chi URL parameter as a UUID. Returns uuid.Nil if validation fails.

func (*Validator) UUIDQuery

func (v *Validator) UUIDQuery(r *http.Request, param string) *uuid.UUID

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.

Jump to

Keyboard shortcuts

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