Feat/split reusable middleware#430
Merged
fredbi merged 6 commits intogo-openapi:masterfrom May 7, 2026
Merged
Conversation
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 Report❌ Patch coverage is 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. |
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change type
Please select: 🆕 New feature or enhancement|🔧 Bug fix'|📃 Documentation update
Short description
Fixes
Full description
Checklist