Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS does not function on swagger.json endpoint #2641

Closed
rcollette opened this issue Apr 25, 2023 · 2 comments
Closed

CORS does not function on swagger.json endpoint #2641

rcollette opened this issue Apr 25, 2023 · 2 comments

Comments

@rcollette
Copy link

My API application is configured to allow cross domain requests by setting:

services.AddCors(
            options =>
            {
                options.AddDefaultPolicy(
                    builder =>
                    {
                        builder.WithOrigins("http://localhost:4200")
                            .AllowAnyMethod()
                            .AllowAnyHeader();
                    });
            });

and

app.UseForwardedHeaders(forwardedHeadersOptions)
            .UseRouting()
            .UseCors()

When a request to any of my APIs contains the Origin request header with a value of http://localhost:4200 the http response header access-control-allow-origin is set to http://localhost:4200. CORS configuration is working.

When a request is made to the swagger.json endpoint rendered by Swashbuckle, and the Origin request header is included as mentioned previously, no access-control-allow-origin header is included in the response.

I am unable to locate any documentation that mentions separate configuration required for Swashbuckle to handle CORS requests.

@Kevin-Andrew
Copy link

@rcollette , I don't believe this is, or has anything to do with Swashbuckle, but I can tell you that we had, what I believe to be, the same problem.

The problem has to do with the order in which you add middleware to the ASP.NET processing pipeline. You showed adding CORS with the services.AddCors(), but you didn't show the rest of your pipeline and middleware, in particular, you didn't show where the Swagger middleware is added. As an example, for us, this was our original code that added all the middleware we use:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
if (UseCompression)
{
    app.UseResponseCompression();
    app.UseMiddleware<BodyStreamWrapperMiddleware>();
}

ConfigureStaticFiles(app, env);

if (UseSwagger)
{
    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger(c => ConfigureSwagger(c));

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c => ConfigureSwaggerUI(c));
}

app.UseHttpsRedirection();

if (UseCors)
{
    app.UseCors();
}

app.UseRouting();
app.UseEndpoints(options =>
{
    options.MapDefaultControllerRoute();
    options.MapSwagger();
    ConfigureEndpointRouting(options);
});
app.UseRequestLocalization();

The key thing to note is that the adding of Swagger comes before the adding of CORS.

What we discovered is that the Swagger middleware, when it knows that the request is for itself, it won't forward the request onto any further middleware handlers. It simply returns the response to the web browser and then stops the server from doing any more processing. So we had to change our code to the following:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
if (UseCompression)
{
    app.UseResponseCompression();
    app.UseMiddleware<BodyStreamWrapperMiddleware>();
}

ConfigureStaticFiles(app, env);

app.UseHttpsRedirection();

// Must come before any "UseSwagger()" calls because the Swagger middleware, when it knows that the request
// is for Swagger, it doesn't forward the request onto the next middleware, it just immediately returns.
if (UseCors)
{
    app.UseCors();
}

if (UseSwagger)
{
    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger(c => ConfigureSwagger(c));

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c => ConfigureSwaggerUI(c));
}

app.UseRouting();
app.UseEndpoints(options =>
{
    options.MapDefaultControllerRoute();
    options.MapSwagger();
    ConfigureEndpointRouting(options);
});
app.UseRequestLocalization();

You now see that the CORS middleware is added to the request pipeline before the Swagger middleware is added, therefore, the CORS middleware will get a chance to process the request before Swagger processes it, and the CORS middleware will be able to properly modify the response with the necessary CORS headers, if needed.

Hopefully that is your issue as well, and if so, then you'll be able to close this bug, as it is not related to Swashbuckle.

@martincostello
Copy link
Collaborator

As noted above, this is likely a middleware ordering issue. Please open a new issue if you still encounter the problem with appropriately ordered middleware so that CORS is applied before Swashbuckle is registered.

@martincostello martincostello closed this as not planned Won't fix, can't repro, duplicate, stale Apr 14, 2024
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

No branches or pull requests

3 participants