feat(http): opt-in filter for HTTP endpoint discovery (CustomizeHttpEndpointDiscovery)#3525
Merged
jeremydmiller merged 1 commit intoJul 20, 2026
Conversation
Message handlers can be split across hosts via Discovery.CustomizeHandlerDiscovery(q => q.Excludes.InNamespace(...)), but HTTP endpoints could not: HttpGraph.DiscoverEndpoints built an HttpChainSource from the assembly list alone, and HttpChainSource's TypeQuery never consulted any user-supplied filter, so an endpoint in an excluded namespace of a scanned assembly still registered. [WolverineIgnore] on the type was the only lever. Add WolverineHttpOptions.CustomizeHttpEndpointDiscovery(Action<TypeQuery>), the HTTP counterpart to HandlerDiscovery.CustomizeHandlerDiscovery. HttpChainSource layers the supplied TypeQuery on top of the built-in endpoint convention: Excludes are subtractive (drop endpoint types, e.g. q.Excludes.InNamespace(...)), Includes are additive (broaden discovery; an included type still only contributes methods carrying a Wolverine HTTP verb attribute). When the method is never called the discovery predicate is byte-for-byte identical to prior behaviour. Test proves both directions against a scanned assembly: by default an endpoint in the excluded namespace is discovered; with the filter it is not, while its sibling namespace still resolves. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds an opt-in HTTP endpoint type filter (CustomizeHttpEndpointDiscovery) to mirror CustomizeHandlerDiscovery, enabling hosts that scan the same assemblies to selectively include/exclude endpoint types (by namespace/type rules) while keeping default discovery behavior unchanged. This integrates into the existing endpoint discovery scan path so the filtering is applied both during normal runtime scanning and during codegen write where the HttpEndpointRegistry manifest is generated for TypeLoadMode.Static.
Changes:
- Added
WolverineHttpOptions.CustomizeHttpEndpointDiscovery(Action<TypeQuery>)and stored the configuredTypeQueryfor downstream discovery. - Threaded the optional
TypeQuerythroughHttpGraphintoHttpChainSource, applying subtractive excludes and additive includes on top of existing conventions. - Added tests + fixtures verifying default discovery is unchanged and that excluding a namespace removes only the excluded endpoint.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/Http/Wolverine.Http/WolverineHttpOptions.cs | Introduces the new opt-in endpoint discovery customization API and stores the configured TypeQuery. |
| src/Http/Wolverine.Http/HttpGraph.cs | Passes the configured discovery filter into the endpoint discovery source. |
| src/Http/Wolverine.Http/HttpChainSource.cs | Applies user-configured excludes/includes in the endpoint type predicate used during discovery scans. |
| src/Http/Wolverine.Http.Tests/http_endpoint_discovery_filter.cs | Adds regression tests for default discovery + namespace exclusion behavior. |
| src/Http/Wolverine.Http.Tests.DifferentAssembly/DiscoveryFilterEndpoints.cs | Adds isolated fixture endpoints in sibling namespaces for the discovery filter tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+17
to
+20
| // Opt-in, additive customization supplied by WolverineHttpOptions.CustomizeHttpEndpointDiscovery. | ||
| // Null unless configured; when set, its Excludes drop endpoint types (so HTTP endpoints honour the | ||
| // same namespace splits as HandlerDiscovery filters) and its Includes broaden discovery. GH-3371. | ||
| private readonly TypeQuery? _userDiscovery; |
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.
Problem
HandlerDiscoverycan include/exclude message handlers by namespace or type viaCustomizeHandlerDiscovery. HTTP endpoint discovery has no equivalent, so an endpoint-bearing assembly scanned by more than one host exposes every endpoint on every host — the only lever is[WolverineIgnore]on the type, which bakes host topology into a shared class.Change
Adds
WolverineHttpOptions.CustomizeHttpEndpointDiscovery(Action<TypeQuery>), the HTTP counterpart toCustomizeHandlerDiscovery:q.Excludes.InNamespace(...)).*Endpoint(s)/[WolverineHttpMethod]convention; an included type still contributes only verb-attributed methods.Additive by default
No behaviour change unless the method is called. Tests assert default discovery is unchanged (both namespaces discovered), and that an exclusion drops one endpoint while its sibling still resolves.
Design point — AOT / Static codegen
The filter should be honoured where discovery is baked at codegen time, not only in the runtime reflection scan, so an excluded endpoint never lands in the generated
HttpEndpointRegistry. I think the implementation is OK, but this should be checked carefully.Closes #3524