Native API versioning for Wolverine.Http (closes #2627)#2633
Merged
jeremydmiller merged 3 commits intoJasperFx:mainfrom May 1, 2026
Merged
Native API versioning for Wolverine.Http (closes #2627)#2633jeremydmiller merged 3 commits intoJasperFx:mainfrom
jeremydmiller merged 3 commits intoJasperFx:mainfrom
Conversation
added 3 commits
April 30, 2026 14:19
Adds URL-segment API versioning to Wolverine.Http driven from an IHttpPolicy. Single dependency on Asp.Versioning.Abstractions 10.0.0 (no Asp.Versioning.Http). * HttpChain.ApiVersion / SunsetPolicy / DeprecationPolicy properties * WolverineHttpOptions.UseApiVersioning configuration surface with fluent Sunset / Deprecate per-version builders * [ApiVersion] attribute resolver — method-wins-over-class, multi-version handlers rejected at startup * ApiVersioningPolicy: route rewriting, sunset/deprecation propagation, duplicate (verb,route,version) detection, IEndpointGroupNameMetadata for OpenAPI document partitioning, Asp.Versioning.ApiVersionMetadata for downstream tooling * ApiVersionHeaderWriter: RFC 9745 Deprecation, RFC 8594 Sunset, RFC 8288 Link, api-supported-versions response headers * DescribeWolverineApiVersions extension for SwaggerUI / Scalar dropdown wiring * WolverineApiVersioningOpenApiOptions.DocumentNameStrategy for customising per-version OpenAPI document names
* OrdersV1Endpoint, OrdersV2Endpoint, OrdersV3PreviewEndpoint sharing the same /orders route — versioning policy rewrites them to /v1/orders, /v2/orders, /v3/orders * WolverineApiVersioningSwaggerOperationFilter reference filter that surfaces deprecation + sunset metadata into OpenAPI operations * Multi-document Swashbuckle setup (default + v1/v2/v3) wired against DescribeWolverineApiVersions for the SwaggerUI dropdown * Scalar.AspNetCore wired for an alternative API explorer UI * Alba integration tests covering route rewriting, response headers, per-version OpenAPI document partitioning, and deprecation flag * IntegrationContext / swashbuckle_integration updated to read the new "default" Swashbuckle document (was implicitly v1)
New docs/guide/http/versioning.md covers attribute usage, UnversionedPolicy modes, sunset/deprecation policies, RFC 9745/8594 header behaviour, and OpenAPI integration patterns for Swashbuckle, Scalar, and Microsoft.AspNetCore.OpenApi. Cross-linked from metadata.md and registered in the Vitepress sidebar.
0f53156 to
51bdfc7
Compare
Member
|
@outofrange-consulting There's enough for another release tomorrow. You okay with this as is? I'll review too, but from your perspective? |
Author
|
I am, I stongly advice you to review the API introduced and the dependency, and I’ll be happy the take it further if you want header/querystring support later ;) |
Member
|
@outofrange-consulting Let's make somebody ask for the header/querystring usage later. I'm starting a review. |
Member
|
@outofrange-consulting We're going for it. It's a little convenient maybe that this will get in just before Wolverine 6, so we can make any API adjustments based on feedback for 6.0. Thanks for taking this on! |
This was referenced May 2, 2026
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.
Closes #2627. Sibling reference: #2401.
Summary
Adds native API versioning to
WolverineFx.Httpwith first-class SwaggerUI / Scalar compatibility. Single dependency onAsp.Versioning.Abstractions(noAsp.Versioning.Http, noMicrosoft.AspNetCore.OpenApi).Produces
/v1/orders,/v2/orders,/v3/ordersautomatically, plus per-version OpenAPI documents and the right RFC headers on every response.What's included
[ApiVersion("1.0")]→/v1/ordersby default.UrlSegmentPrefixandUrlSegmentVersionFormatterare both overridable.[ApiVersion]takes precedence over class-level. Multiple[ApiVersion]attributes on a single method are explicitly rejected at startup.UnversionedPolicywith three modes:PassThrough(default),RequireExplicit(throws at startup if any chain lacks[ApiVersion]),AssignDefault(assigns a configuredDefaultVersion).Sunset("1.0").On(date).WithLink(uri, title?, type?)builders. Attribute-driven[ApiVersion(..., Deprecated = true)]takes precedence over options-driven deprecation per chain.Deprecation(withtruetoken when no date), RFC 8594Sunset, RFC 8288Link, plusapi-supported-versions. Two independent toggles (EmitDeprecationHeaders,EmitApiSupportedVersionsHeader).(verb, original-route, version)triple throw at bootstrap with both display names in the message.IEndpointGroupNameMetadata(already plumbed through toApiDescription.GroupName).WolverineApiVersioningOpenApiOptions.DocumentNameStrategylets users customise the document name (defaultv{major}).app.DescribeWolverineApiVersions()returns one description per discovered version for wiring SwaggerUI / Scalar dropdowns.IOperationFilter(WolverineApiVersioningSwaggerOperationFilter) lives inWolverineWebApias copy-paste reference code — setsOpenApiOperation.Deprecatedand emits anx-api-versioningextension carrying sunset date and links.Dependency choice
Asp.Versioning.Abstractions10.0.0 only — notAsp.Versioning.Http. Routing is driven fromIHttpPolicy, so we need the types (ApiVersion,ApiVersionAttribute,SunsetPolicy,DeprecationPolicy,ApiVersionMetadata,LinkHeaderValue) but not the readers, version sets, or DI policy manager. Smaller surface, no MVC-centric assumptions.Asp.Versioning.Httpis verified absent from the transitive closure (dotnet list package --include-transitive).Default URL-segment format
[ApiVersion("1.0")]produces/v1/orders(major-only) by default. Users wanting/v1.0/orderssetUrlSegmentVersionFormatter = v => v.ToString(). Documentation explicitly notes both options.Implementation notes
IApiDescriptionand external tools (Swashbuckle, MS.AspNetCore.OpenApi) read it. The policy attachesIEndpointGroupNameMetadataso document partitioning works automatically with Swashbuckle'sDocInclusionPredicateor the equivalent ASP.NET Core mechanism.ApiVersionEndpointHeaderStateandApiVersionHeaderWriterare public. The state record is part of the observable contract for user OpenAPI filters; the writer is referenced by Wolverine's dynamic codegen (empirically verified —internalproduces CS0122 in generated source).Tests
Wolverine.Http.Tests(net9.0)api_versioning_integration_tests.cs)Smoke test on the WolverineWebApi sample confirms
/v1/orders,/v2/orders,/v3/ordersall 200 with the expectedDeprecation/Sunset/Link/api-supported-versionsheaders, and/swagger/{default,v1,v2,v3}/swagger.jsonall serve correctly.Test plan
dotnet buildsucceeds on net8.0 / net9.0 / net10.0dotnet test src/Http/Wolverine.Http.Testsis greenWolverineWebApiand visit/swagger— confirm dropdown showsdefault,v1,v2,v3and the v1 endpoint shows the deprecated marker/scalar/v1— confirm the Scalar UI renders versioned operationscurl -i /v1/ordersshowsDeprecation,Link,api-supported-versionsheaderscurl -i /v3/ordersshowsSunset,Link,api-supported-versionsheadersdotnet list src/Http/Wolverine.Http package --include-transitiveconfirmsAsp.Versioning.Httpis not presentDocumentation
docs/guide/http/versioning.mdcovers attribute rules, URL-segment strategy, the threeUnversionedPolicymodes, sunset/deprecation policies, OpenAPI integration (Swashbuckle + Scalar + MS.AspNetCore.OpenApi). Cross-linked frommetadata.md. Sidebar entry registered indocs/.vitepress/config.mts.