Describe the bug
The new Endpoint Routing-based MapSwaggerUI introduced in #3822 uses a catch-all path pattern on the sub application builder, forcing all requests with a specific prefix through the middleware. If the path can not be served by the SwaggerUI Middleware (i.e. "swagger/some-random-path.json") an Internal Server Error will be raised because the request has reached the end of the application builder pipeline without producing a result.
The request reached the end of the pipeline without executing the endpoint: 'swagger/{**path}'.
Please register the EndpointMiddleware using 'IApplicationBuilder.UseEndpoints(...)' if using routing.
Because a wildcard route was added and it's the only endpoint on the sub-application/pipeline created by MapSwaggerUI, it is expected to produce something. SwaggerUIMiddleware invokes the next RequestDelegate if it internally does not match anything, but there's nothing to execute and thus the pipeline fails.
This doesn't happen with non-endpoint-routing usage of SwaggerUIMiddleware because there's no wildcard match involved; invoking the next delegate will run the rest of "normal" routing which will surface a 404 instead.
Note: I have not verified but I believe this also impacts MapReDoc and ReDocMiddleware
Expected behavior
Accessing a path that does not exist, should return a 404 response and not a 500 Server Error + Exception
Actual behavior
An internal server error is raised because no endpoint was executed
Steps to reproduce
- Add the following to an application:
app.UseEndpoints(endpoints =>
{
endpoints.MapSwaggerUI()
.AllowAnonymous();
});
- Access
/swagger/i-dont-exist.json or any other URL that can't be satisfied by the SwaggerUI Middleware.
- Fail
Exception(s) (if any)
System.InvalidOperationException: The request reached the end of the pipeline without executing the endpoint: 'swagger/{**path}'. Please register the EndpointMiddleware using 'IApplicationBuilder.UseEndpoints(...)' if using routing.
at Microsoft.AspNetCore.Builder.ApplicationBuilder.<>c.<Build>b__25_0(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|7_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Swashbuckle.AspNetCore version
10.2.1
.NET Version
10
Anything else?
I can think of at least two ways this can be solved:
- Add a flag on
SwaggerUIOptions and/or SwaggerUIMiddleware that tells that middleware that it needs terminal behavior and should return a 404 if it cannot serve the request and then plumb that through MapSwaggerUI, etc.
- Change the registration of
MapSwaggerUI to remove-then-restore the matched endpoint:
var pipeline = endpoints.CreateApplicationBuilder()
.UseSwaggerUI(options)
.Build();
return endpoints.Map(GetRoutePattern(options.RoutePrefix), async ctx =>
{
var orig = ctx.GetEndpoint();
ctx.SetEndpoint(null);
await pipeline(ctx);
ctx.SetEndpoint(orig);
});
This will cause routing to continue if the SwaggerUIMiddleware cannot handle the request. Lack of an endpoint prevents the ApplicationBuilder from throwing; instead it will produce a 404 response
Describe the bug
The new Endpoint Routing-based
MapSwaggerUIintroduced in #3822 uses a catch-all path pattern on the sub application builder, forcing all requests with a specific prefix through the middleware. If the path can not be served by the SwaggerUI Middleware (i.e. "swagger/some-random-path.json") an Internal Server Error will be raised because the request has reached the end of the application builder pipeline without producing a result.Because a wildcard route was added and it's the only endpoint on the sub-application/pipeline created by
MapSwaggerUI, it is expected to produce something.SwaggerUIMiddlewareinvokes the nextRequestDelegateif it internally does not match anything, but there's nothing to execute and thus the pipeline fails.This doesn't happen with non-endpoint-routing usage of
SwaggerUIMiddlewarebecause there's no wildcard match involved; invoking thenextdelegate will run the rest of "normal" routing which will surface a 404 instead.Note: I have not verified but I believe this also impacts
MapReDocandReDocMiddlewareExpected behavior
Accessing a path that does not exist, should return a 404 response and not a 500 Server Error + Exception
Actual behavior
An internal server error is raised because no endpoint was executed
Steps to reproduce
/swagger/i-dont-exist.jsonor any other URL that can't be satisfied by the SwaggerUI Middleware.Exception(s) (if any)
Swashbuckle.AspNetCore version
10.2.1
.NET Version
10
Anything else?
I can think of at least two ways this can be solved:
SwaggerUIOptionsand/orSwaggerUIMiddlewarethat tells that middleware that it needs terminal behavior and should return a 404 if it cannot serve the request and then plumb that throughMapSwaggerUI, etc.MapSwaggerUIto remove-then-restore the matched endpoint:This will cause routing to continue if the
SwaggerUIMiddlewarecannot handle the request. Lack of an endpoint prevents the ApplicationBuilder from throwing; instead it will produce a 404 response