Skip to content

chore(body): accept another data types - #66

Merged
moutonjeremy merged 12 commits into
mainfrom
feat/v3.3.0
Oct 19, 2026
Merged

moutonjeremy merged 12 commits into
mainfrom
feat/v3.3.0

Conversation

@moutonjeremy

Copy link
Copy Markdown
Member

Multiple change for accept others bodies than json

moutonjeremy and others added 12 commits October 19, 2026 19:11
…m body schema

The JSON decoder matches keys case-insensitively, so a field tagged
uri:"id" without json:"-" could be overwritten by {"id": "..."} in the
request body. parseInput now decodes the body first, then binds the path,
query and headers, which therefore always win.

generateSchema skipped path/query/header fields but not uri ones, so path
parameters leaked into the documented request body. uri and body:"raw"
fields are now excluded too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AuthError gains an Err field and an Unwrap method, so an AuthErrorHandler
can use errors.Is / errors.As on the error returned by ValidateToken
(expired token, revoked device...) instead of comparing messages. When
that cause implements HTTPStatusError, its status replaces the default
401.

MultiSchemeAuthMiddleware and SmartAuthMiddleware now go through
Config.AuthErrorHandler when one is set; without it they keep their
legacy body and status.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TokenValidatorFunc turns a plain func(token) (*AuthContext, error) into
an AuthorizationService. Roles and scopes are read from the returned
AuthContext; resource permissions fail with
ErrResourceAuthorizationNotConfigured, so such a route answers 500 and
never grants access by default.

A service that needs the request to validate a Bearer token can
implement ContextTokenValidator; ValidateTokenCtx is then preferred over
ValidateToken, including in BearerTokenMiddleware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Config.AuthenticateFirst places an authentication handler at the head of
every protected route: a request without valid credentials is rejected
before its body is decoded, and route middlewares can call
GetAuthContext. Roles and resource permissions are still checked after
the input is parsed. validateAuthorization is split into authenticate
and authorize to make this possible; the default flow is unchanged.

OpenAPIOptions.Middlewares registers handlers that run before the input
is read, after the group middlewares and the authentication handler.

Errors raised before the handler go through a single respondError, used
by both the authentication handler and the route wrapper.

Protected routes now document 401, and 403 when they check roles, scopes
or resource permissions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem follows RFC 9457, with Code (a stable identifier) and Errors (the
per-field entries) as extension members. Any error value can implement
ContentTyper to choose the Content-Type it is sent and documented with;
Problem answers application/problem+json.

With Config.ProblemDetails, every error produced by the library (parse,
validation, authentication, 404/405, serialization) is a Problem, and the
400/401/403/404 and validation responses of the spec point to the Problem
schema under application/problem+json. ProblemDetails takes precedence
over DefaultErrorShape; the custom error handlers keep priority.

Config.ValidationStatusCode sets the status of validation errors (default
422), at runtime and in the spec. When it collides with the 400 parse
response, both are documented under one key. Config.ProblemCodes renames
the Code of a category.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OpenAPIOptions.SuccessStatus sets the status of a successful response
(201, 204...), at runtime and in the spec. At runtime a status other than
200 set by the handler still wins, then the HTTPStatus() of the output,
then SuccessStatus. A 204 is now sent without a body instead of null, and
documented without content.

OpenAPIOptions.Responses adds OpenAPI response objects as-is, merged last.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A []byte field tagged body:"raw" receives the request body as-is,
whatever its Content-Type, instead of going through Fiber's body binder
(which rejects application/octet-stream). The body is copied, since
Fiber reuses its buffers, and validation applies to its length. More than
one such field, or one that is not a []byte, panics when the route is
registered.

The spec documents such a body as {type: string, format: binary} under
OpenAPIOptions.RequestContentType (application/octet-stream by default);
RequestContentType also sets the media type of a JSON body.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An output that implements Responder writes its own status, headers and
body, instead of being encoded as JSON: binary content, streams or
Server-Sent Events. The check is made once, when the route is
registered. RawResponse covers a binary body.

OpenAPIOptions.ResponseContentType sets the media type of the success
response: a binary schema (a string one for text/...) for a Responder,
the JSON schema otherwise, in which case the JSON is also sent with that
Content-Type.

The README gets a complete Server-Sent Events example, with what stays
outside the library: compression and WriteTimeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The detail of a validation Problem came from categorizeError, which uses
the Go field name ("Name"), while its entries use the name the client
sent ("name"). The detail now repeats the first entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One section per feature (AuthenticateFirst, auth error causes,
TokenValidatorFunc, problem details, raw bodies, success status, route
middlewares), the new Config fields, and a "What's new in v3.3" box that
calls out the two fixes that change behavior: path/query/header values
now win over the body, and uri fields leave the documented body.

Also fixes the default auth error example, which still showed the
pre-v3 flat shape, and the minimum Go version (1.27).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mirrors a sync server using AuthenticateFirst, ProblemDetails,
ValidationStatusCode, raw bodies, RawResponse, SuccessStatus, Responses
and route middlewares, and checks that every status and Content-Type
returned at runtime is documented in the spec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Config.AuthenticateFirst is removed: every protected route now checks
the credentials in a handler placed at the head of its chain, before the
route middlewares and before the input is read. A request that fails
authentication gets its 401 without its body being decoded, even when
that body is malformed or invalid (it used to get a 400 or 422). This
saves the decoding and validation work on rejected requests, and keeps an
unauthenticated client from probing the validation rules of a route.

Roles and resource permissions are still checked after the input is
parsed, since they need it. validateAuthorization, now unused, is gone.

BREAKING CHANGE: on a protected route, authentication errors (401) now
take precedence over parse (400) and validation (422) errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@moutonjeremy
moutonjeremy merged commit e59fa09 into main Oct 19, 2026
4 checks passed
@moutonjeremy
moutonjeremy deleted the feat/v3.3.0 branch October 19, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant