Skip to content

Feat/split reusable middleware#430

Merged
fredbi merged 6 commits intogo-openapi:masterfrom
fredbi:feat/split-reusable-middleware
May 7, 2026
Merged

Feat/split reusable middleware#430
fredbi merged 6 commits intogo-openapi:masterfrom
fredbi:feat/split-reusable-middleware

Conversation

@fredbi
Copy link
Copy Markdown
Member

@fredbi fredbi commented May 7, 2026

Change type

Please select: 🆕 New feature or enhancement|🔧 Bug fix'|📃 Documentation update

Short description

Fixes

Full description

Checklist

  • I have signed all my commits with my name and email (see DCO. This does not require a PGP-signed commit
  • I have rebased and squashed my work, so only one commit remains
  • I have added tests to cover my changes.
  • I have properly enriched go doc comments in code.
  • I have properly documented any breaking change.

fredbi and others added 5 commits May 7, 2026 21:14
Move SwaggerUI, Redoc, RapiDoc, SwaggerUIOAuth2Callback and Spec, along
with their option helpers, out of the middleware package into a new
github.com/go-openapi/runtime/server-middleware/docui package. The new
module is stdlib-only, so any net/http application can mount a docs
site without dragging in go-openapi/loads, analysis, spec or validate.

Package middleware retains every old public name as a deprecated forwarder:
type aliases for SwaggerUIOpts/RedocOpts/RapiDocOpts/SpecOption/
UIOption, and var aliases for the function values (SwaggerUI, Redoc,
RapiDoc, SwaggerUIOAuth2Callback, Spec, WithUIBasePath, ...). User code
keeps compiling unchanged. Spec forwards to docui.ServeSpec, which was
renamed from Spec to avoid the awkward docui.Spec identifier.

middleware/context.go now calls docui directly. A handful of helpers
(UIOptions, UIOptionsWithDefaults, FromCommonToAnyOptions,
ToCommonUIOptions) had to be exported because they cross the new module
boundary in Context.uiOptionsForHandler.

> NOTE:
> The unification of Redoc/RapiDoc/SwaggerUI option structs that the
> roadmap suggests for this step is intentionally deferred: keeping the
> three structs distinct in docui is what allows the clean type aliases
> above. Tracked for a follow-up.

* fixes go-openapi#257

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
Introduce a new server-middleware/mediatype package with a typed
MediaType value, a Set type, and a single asymmetric Matches rule used
by both server-side validation and Accept-header negotiation. The rule
faithfully reproduces the parameter-aware match from go-openapi#136 — bare types
must agree (with wildcards), and if the receiver carries parameters
the constraint's parameters must be a subset (case-insensitive
values).

Both call sites are rewired on top of mediatype:

  - middleware.validateContentType uses MediaType.Matches; the
    mediaTypeMatches helper is removed.
  - middleware.NegotiateContentType uses Set.BestMatch; normalizeOffer
    is no longer applied to negotiation candidates. Encoding
    negotiation (NegotiateContentEncoding) is unchanged — encoding
    tokens carry no parameters.

The default behavior of NegotiateContentType therefore changes: an
Accept entry like "text/plain;charset=ascii" no longer silently
matches a "text/plain;charset=utf-8" offer. For applications that
relied on the loose pre-v0.30 match, an explicit opt-out is provided:

  - WithIgnoreParameters(bool) NegotiateOption — a per-call option
    that strips parameters from both sides before matching.
  - Context.SetIgnoreParameters(bool) — server-wide toggle, threaded
    into the internal Respond / ResponseFormat negotiation calls.

The opt-out is documented with a runnable godoc Example
(ExampleWithIgnoreParameters) showing both modes side-by-side.

Tests:

  - mediatype/* exhaustive table-driven coverage: parsing, wildcard
    handling, parameter subset rule, q-value clamping, BestMatch
    against the full historic negotiate_test.go matrix.
  - middleware/negotiate_test split into TestNegotiateContentTypeDefault
    (param-honouring) and TestNegotiateContentTypeIgnoreParameters
    (legacy mode), plus a multi-Accept-header guard
    (RFC 7230 §3.2.2) and the godoc Example.

* fixes go-openapi#386

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
Move the content-negotiation helpers out of middleware/ into a new
server-middleware/negotiate package. The header parsing utilities they
depend on travel along as a nested server-middleware/negotiate/header
package — they were already stdlib-only and used nowhere else.

Naming in the new package drops the redundant Negotiate prefix:

  - NegotiateContentType     -> negotiate.ContentType
  - NegotiateContentEncoding -> negotiate.ContentEncoding
  - NegotiateOption          -> negotiate.Option
  - WithIgnoreParameters     unchanged

The old middleware names remain as deprecated forwarders in
middleware/seam.go (type alias for Option, var aliases for the
function values), so user code keeps compiling unchanged.

middleware/context.go now calls negotiate.ContentType directly and
constructs []negotiate.Option in its negotiateOpts helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
The docui package now exposes a functional-options API (Redoc, RapiDoc,
SwaggerUI, SwaggerUIOAuth2Callback take a next handler and variadic
Option) along with companion Use* variants returning func(http.Handler)
http.Handler.

The middleware package keeps its v0.29 struct-based handlers as
deprecated forwarders in seam.go: each toFuncOptions() bridges the
struct to the new option set, omitting zero-valued fields so empty
structs don't clobber filled-in defaults. APIHandler{,SwaggerUI,RapiDoc}
delegate to APIHandlerWithUI, with default basepath/title injection now
in a single place.

SwaggerUI defaults (preset, styles, favicons) apply after user opts in
swaggeruiSetup, fixing a regression where WithSwaggerUIOptions(empty)
would erase them.

Tests: all UI handlers covered by httptest-based unit tests including
the WithSwaggerUIOptions clobber regression. Shared serveUI moved to
render.go; shared test fixtures (testSpec, badTemplate,
malformedTemplate) live in render_test.go.

* fixes go-openapi#257

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
Add a deprecated forwarding shim for the middleware/header package, which
had moved to server-middleware/negotiate/header without leaving the old
import path resolvable.

Convert the negotiate seams (NegotiateContentType, NegotiateContentEncoding,
WithIgnoreParameters) from var aliases to func wrappers so the symbols
remain immutable.

Update README with the v0.30 announcements: the new server-middleware
module, the parameter-honouring change in NegotiateContentType, the
docui extraction, and the removal of the EnsureDefaults* helpers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

❌ Patch coverage is 86.39456% with 100 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.03%. Comparing base (d7fb83c) to head (2f14f29).
⚠️ Report is 1 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
middleware/seam.go 49.23% 43 Missing and 23 partials ⚠️
server-middleware/negotiate/negotiate.go 79.36% 7 Missing and 6 partials ⚠️
server-middleware/mediatype/set.go 89.23% 7 Missing ⚠️
server-middleware/docui/options.go 90.16% 3 Missing and 3 partials ⚠️
middleware/context.go 87.09% 4 Missing ⚠️
middleware/validation.go 50.00% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #430      +/-   ##
==========================================
+ Coverage   81.67%   84.03%   +2.35%     
==========================================
  Files          50       56       +6     
  Lines        3411     3676     +265     
==========================================
+ Hits         2786     3089     +303     
+ Misses        510      446      -64     
- Partials      115      141      +26     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
@fredbi fredbi merged commit 52d35ad into go-openapi:master May 7, 2026
21 checks passed
@fredbi fredbi deleted the feat/split-reusable-middleware branch May 7, 2026 20:26
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