-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
app := rex.New(validation.WithValidation(validation.NewConfig(
validation.WithCodec(XMLCodec{}),
validation.WithStrictResponses(true),
)))validation.WithValidation(nil) takes the defaults.
There is no field-by-field merge. A partial struct literal leaves everything else at its zero value:
// Wrong: Codecs nil (no codecs at all), ValidateResponses false.
validation.WithValidation(&validation.Config{StrictResponses: true})
// Right.
validation.WithValidation(validation.NewConfig(validation.WithStrictResponses(true)))The merge used to exist and behaved as a trap: fields it forgot were silently ignored, fields it copied unconditionally were zeroed by a partial literal, and a deliberate zero could not be expressed at all.
Note how the negative phrasing of AllowUnknownFields interacts with this: the
zero value has to be the safe one, or a partial literal would quietly opt out
of rejection.
type Config struct {
Codecs []Codec // default [JSONCodec{}]; first is the Accept default
StrictResponses bool // default false
ValidateResponses bool // default true
AllowUnknownFields bool // default false — rejection is on
}WithCodec(c) |
append a codec |
WithValidateResponses(bool) |
check response bodies against declared schemas |
WithStrictResponses(bool) |
undocumented status → 500 |
WithAllowUnknownFields() |
⚠ permit undeclared request members |
validation.NewConfig(
// Responses are checked, and every status must be documented.
validation.WithValidateResponses(true),
validation.WithStrictResponses(true),
// Unknown fields rejected — the default, stated for the reader.
)For a service with an established client you cannot change:
validation.NewConfig(
validation.WithAllowUnknownFields(), // deliberate, and worth a comment
validation.WithValidateResponses(true),
)type MiddlewareConfig struct {
Registry *codecRegistry
Validator routeValidator
Strict bool
ValidateResp bool
RejectUnknown bool
Logger rx.Logger
}Set the logger. A strict-mode rejection describes the server's own internals,
so the client gets a generic 500 — without somewhere to write the specifics the
information is simply lost. The extension configures it from r.Logger().
ValidationFactory(cfg) builds the per-route middleware from it if you are
composing a chain yourself. ValidationMiddleware(cfg) is the deprecated
plain-http form — it has to find the route's schemas at request time, where
the factory reads them once at freeze.
Both extensions read the same route interface. Register both and one declaration produces validation and documentation together:
app := rex.New(
validation.WithValidation(nil),
openapi.WithOpenAPI(nil),
)There is nothing to keep in sync, which is the point of the contract living in
rextension rather than in either extension.
rextension-validation — request/response validation and content negotiation for Rex · MIT · © 2026 Kryovyx