-
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.