Skip to content

feat(http): opt-in filter for HTTP endpoint discovery (CustomizeHttpEndpointDiscovery)#3525

Merged
jeremydmiller merged 1 commit into
JasperFx:mainfrom
uniquelau:feat/customize-http-endpoint-discovery
Jul 20, 2026
Merged

feat(http): opt-in filter for HTTP endpoint discovery (CustomizeHttpEndpointDiscovery)#3525
jeremydmiller merged 1 commit into
JasperFx:mainfrom
uniquelau:feat/customize-http-endpoint-discovery

Conversation

@uniquelau

@uniquelau uniquelau commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Problem

HandlerDiscovery can include/exclude message handlers by namespace or type via CustomizeHandlerDiscovery. 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 to CustomizeHandlerDiscovery:

  • Excludes are subtractive — drop endpoint types (e.g. q.Excludes.InNamespace(...)).
  • Includes are additive — broaden past the built-in *Endpoint(s) / [WolverineHttpMethod] convention; an included type still contributes only verb-attributed methods.
  • Null until called — the predicate then reduces to today's built-in convention exactly.

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

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>
Copilot AI review requested due to automatic review settings July 20, 2026 12:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 configured TypeQuery for downstream discovery.
  • Threaded the optional TypeQuery through HttpGraph into HttpChainSource, 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;
@jeremydmiller
jeremydmiller merged commit a68382c into JasperFx:main Jul 20, 2026
29 of 30 checks passed
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.

Let HTTP endpoint discovery honour discovery filters (CustomizeHttpEndpointDiscovery)

3 participants