feat(httputil): add Bind/BindEmpty request binding from path and query; v1.6.0
Bind and BindEmpty fill Req from path/query/json struct tags and validate once, extending the typed decode->validate->call->encode pipeline to routes with identifiers and filters. Conversion via builtins + encoding.TextUnmarshaler (uuid.UUID, time.Time); malformed value -> 400 naming the parameter; default: applies only when absent; repeated query -> slice; mis-tagged struct panics at wiring. Purely additive; existing adapters unchanged. Coordinated lockstep v1.6.0.
This commit is contained in:
@@ -6,6 +6,37 @@ This module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html
|
||||
|
||||
---
|
||||
|
||||
## [1.6.0] — 2026-08-13
|
||||
|
||||
Minor — request binding from path and query, not only the JSON body.
|
||||
|
||||
### Added
|
||||
|
||||
- **`httputil.Bind[Req, Res]`** and **`httputil.BindEmpty[Req]`** — a fourth adapter family
|
||||
that fills `Req` from the path, the query string **and** the body, each field declaring its
|
||||
source with a struct tag (`path:` / `query:` / `json:`), then validates the assembled struct
|
||||
once with the same `valid.Validator`. The handler signature is identical to `Handle` /
|
||||
`HandleEmpty`; `WithStatus` and the full error-mapping pipeline are reused unchanged.
|
||||
- Conversion covers `string`, the sized integer/unsigned/float types, `bool`, and any type
|
||||
whose pointer implements `encoding.TextUnmarshaler` — so `uuid.UUID` and `time.Time` bind
|
||||
with no special-casing and no new dependency in `web`.
|
||||
- A conversion failure is `ErrInvalidInput` naming the parameter (**400, never 500**).
|
||||
- `default:` applies only when a parameter is **absent** (a present-but-empty `?q=` is left
|
||||
as the zero value). Repeated query parameters bind to a slice; a comma inside a single value
|
||||
is not split. A bodiless `GET`/`DELETE` is not an error — `BindEmpty` retires the
|
||||
`HandleEmpty` empty-body (`io.EOF`) trap for routes keyed only by a path parameter.
|
||||
- The struct is reflected over **once per type and cached**. A field with more than one source
|
||||
tag, an unsupported field type, or a `default:` that is not a valid value for its field all
|
||||
**panic at wiring** — a mis-tagged struct fails the service at boot, not on a request.
|
||||
|
||||
### Changed
|
||||
|
||||
- `HandlerFunc`'s doc comment no longer advertises itself for path/query parameters — those go
|
||||
through `Bind` now; it remains the escape hatch for genuinely custom responses (streaming,
|
||||
file downloads, non-JSON). `Handle`, `HandleNoBody`, `HandleEmpty` and `HandlerFunc` are
|
||||
behaviourally unchanged.
|
||||
- Bumped `contracts`, `core` to v1.6.0.
|
||||
|
||||
## [1.5.0] — 2026-08-09
|
||||
|
||||
Minor — configurable success status on the httputil handler adapters.
|
||||
|
||||
Reference in New Issue
Block a user