binder / Docs / API reference

API reference

The whole exported surface of uradical.io/go/binder: three functions, three types, two variables and five sentinel errors. The generated reference lives at pkg.go.dev; this page is the same material with the reasoning attached.

Functions

Bindfunc

func Bind(r *http.Request, i interface{}) error

Binds an HTTP request into the struct i points at. The target must be a non-nil pointer to a struct; anything else is ErrInvalidTarget. Equivalent to BindWithOptions(r, i, BindOptions{}).

Fields reflection cannot set — unexported ones — are ignored even when they carry a tag. If the target implements Validator, Validate runs after every field is bound and its error is returned.

Returns an error when

  • the target is not a non-nil pointer to a struct — ErrInvalidTarget;
  • a value will not convert to its field's type — a *BindError;
  • a field tagged required had no value — ErrMissingRequired;
  • the body exceeded MaxBodySizeErrBodyTooLarge;
  • the body could not be parsed — ErrMalformedBody;
  • Validate failed.

BindWithOptionsfunc

func BindWithOptions(r *http.Request, i interface{}, opts BindOptions) error

Bind with per-call configuration. The zero BindOptions behaves exactly as Bind does, so this is the function to reach for rather than mutating package state when only one endpoint needs a different limit.

A nil request is ErrInvalidTarget rather than a panic.

BindStructfunc

func BindStruct(field reflect.Value, data map[string]interface{}) error

Binds a decoded map into a struct value directly, without a request. This is the machinery behind nested struct binding, exported for the cases where you already hold decoded data — a websocket frame, a queue message, a batch element — and want the same tag semantics.

Handles pointer and non-pointer values, allocating a nil pointer as needed. Fields are matched on body, falling back to json. Most code should use Bind instead.

Types

BindOptionstype

type BindOptions struct {
	// MaxBodySize overrides the package-level MaxBodySize for this call.
	// Zero leaves the package setting in force, and a negative value
	// removes the limit for this call alone.
	MaxBodySize int64

	// DisallowUnknownFields makes binding fail with ErrUnknownField when
	// the request body carries a top-level key that no field of the target
	// binds. Keys nested inside objects are not inspected.
	DisallowUnknownFields bool
}

See Options for how each behaves.

BindErrortype

type BindError struct {
	Field   string // name of the Go struct field
	Source  string // tag source the value was read from, such as "query"
	Name    string // key looked up in that source
	Message string // complete description of what went wrong
	Err     error  // underlying cause, reachable with errors.Is and errors.As
}

func (e *BindError) Error() string
func (e *BindError) Unwrap() error

Describes a failure to bind one field. Reach it with errors.As; the fields, not the message, are the stable part. See Error handling.

Validatortype

type Validator interface {
	Validate() error
}

Implemented by a target that wants its own checks run after binding. See Validation.

Variables and constants

MaxBodySizevar

var MaxBodySize = DefaultMaxBodySize

The largest request body, in bytes, that Bind will read. A larger body is rejected with ErrBodyTooLarge rather than buffered. Zero or less disables the limit.

Read on every call, so set it during initialisation rather than while requests are in flight.

DefaultMaxBodySizeconst

const DefaultMaxBodySize int64 = 10 << 20 // 10 MB

The value MaxBodySize starts at. Its value is not part of the compatibility contract; the constant is, so code that wants to restore the default can name it.

Sentinel errors

Match these with errors.Is. The message text is not stable; these are.

SentinelReturned when
ErrMalformedBodyThe body could not be parsed as the format its Content-Type declares.
ErrBodyTooLargeThe body exceeded the effective MaxBodySize.
ErrInvalidTargetThe target was not a non-nil pointer to a struct, or the request was nil.
ErrMissingRequiredA field tagged required had no value. Wrapped by a BindError.
ErrUnknownFieldDisallowUnknownFields was set and the body carried a key nothing binds.

Struct tag summary

TagSource
path:"name"Path parameters, via Request.PathValue
query:"name"URL query parameters
body:"name"Request body, JSON or form-encoded by Content-Type
json:"name"Request body; for tags shared with serialisation
cookie:"name"Request cookies
header:"name"Request headers, matched case-insensitively

Precedence when a field carries several: path, query, body, json, cookie, header. Options are ,omitempty and ,required. See Binding sources.