Reputation: 177
I have a .NET lambda API that I was previously using Swashbuckle to generate a swagger.json file that was given to an external site to use. I am now trying to setup so the swagger.json file is is generated by the API and available through a url for the external site to us ie: mylambdaapi.com/swagger/v2/swagger.json. I was able to get this working by adding a dummy event to my template when pushing to aws as follows.
"SwaggerJson": {
"Type": "Api",
"Properties": {
"Path": "/swagger/v2/swagger.json",
"Method": "GET"
}
}
This works for just accessing the file normally, however the external site will run into CORS "No 'Access-Control-Allow-Origin' header" issues when trying to load the json. Is there any way to force the generation to use "Access-Control-Allow-Origin" in this case? Or is this not feasible in this way? I'm working off what another developer had built previously so I'm trying not to rewrite every, however I'm open to another method as long as it is able to produce some swagger json that the external site can consume.
EDIT: I should note that I am using API gateway, hover the swagger.json is only used for documentation purposes for the external site.
Upvotes: 1
Views: 3817
Reputation: 1003
I ran into this recently because the GET request for the swagger.json was not generating a CORS Options request. The reason for this is the GET request for http://example.com/api/whatever/swagger.json is a Simple Request for the following reasons: It is a GET request with only Accept and default browser headers added. Since Simple Requests do not generate a CORS Preflight OPTIONS request, we have to tackle the CORS issues a different way.
When there is no OPTIONS request, the asp.net core CORS functionality was not triggered leading to the CORS error for the browser.
To resolve this I had to use a custom middleware:
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/api/docs/swagger"))
{
context.Response.Headers["Access-Control-Allow-Origin"] = "*";
}
return next.Invoke();
});
app.UseSwagger(c => { c.RouteTemplate = "api/docs/swagger/{documentName}/swagger.json"; });
It is similar to what DoubleHolo posted but I added the if statement since I don't want my entire API to be accessible from any URL.
Upvotes: 1
Reputation: 177
Attempted to use UseCors() functionality however that did not work. I was able to fix the issue by adding an anonymous function to handle the response before UseSwagger.
The following snip-it is from the Configure function in my startup.
app.Use((context, next) =>
{
context.Response.Headers["Access-Control-Allow-Origin"] = "*";
return next.Invoke();
});
app.UseSwagger();
Upvotes: 4