NSwag introduced automatic handling of X-Forwarded-* headers a few months ago (https://github.com/RicoSuter/NSwag/pull/2196). Is there an equivalent in Swashbuckle?
Are you just trying to get Swashbuckle to work in a reverse-proxy environment, or is there some specific reason why you need the documents server property populated based on reverse proxy headers?
If it's the former, then the recommended way to support reverse proxy environments is to use relative URLs in your Swagger configuration. See #1253 for details.
I'm trying to get Swashbuckle to work in a reverse-proxy environment. I don't have a problem with referencing the generated .json, but I don't want to glue the app to a specific hosting model, so I'd like to avoid specifying the path via .UsePathBase and have the generator taking it from X-Forwarded-Prefix.
There is a further issue in reverse proxy scenarios you may want to consider - authentication.
We have clients going to, say https://foo.myco.com/api/swagger and https://bar.myco.com/api/swagger which resolves to the same actual instance of a service behind the reverse proxy.
They need to get an OAuth2 token to use the "Try it Out" feature.
The authentication service url will be https://foo.myco.com/oauth and https://bar.myco.com/oauth respectively, so the swagger doc needs to reflect that.
If you were looking to handle reverse proxy environments automatically then it would be great to support this aspect too.
Our current solution is a PreSerialize filter to alter the TokenUrl for the OAuth2Scheme on every request.
Also bear in mind that Microsoft use X-Original-Host rather than the "standard" X-Forwarded-Host" for their Application Gateway RP so perhaps support the ability to override the header deemed to be the host header?
@Leon99 - if you use the _relative_ URL approach as described here https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1253#issuecomment-530850121, you're entire Swagger setup should be completely agnostic of the hosting model and there should be no need to leverage UsePathBase. Did you try the approach described?
@domaindrivendev yes I did - the base URL is not generated correctly, therefore execution doesn't work. As far as I understand, the only way to generate that correctly is to get them from X-Forwarded-*. Otherwise, it will try to use https://myapi.com/myresource instead of https://myapi.com/some/root/path/myresource and, expectedly, fail.
We also have this issue. Using reverse proxy on IIS the base url isn't generated correctly.
I have this issue as well. When running locally, the curl requests are sent to localhost:5000/someEndpoint correctly, but when deployed behind nginx, the swagger json file loads just fine, but the the 'try it out' curl request are directed to the base url without consideration of sub-directories. Ie. if the app is running at myapp.com/api/v1/someEndpoint, the curl request goes to myapp.com/someEndpoint instead of myapp.com/api/v1/someEndpoint
@rob893 I'm going to add automatic support for detecting the origin url based on some common reverse proxy headers (X-Forward-*) and this should solve the reverse proxy problem for most cases. In the meantime OR if you need to customize for non-standard proxy headers you can do so by enriching the generated Swagger/OpenAPI document before it's serialized. For example ...
app.UseSwagger(c =>
{
c.PreSerializeFilters.Add((swaggerDoc, httpRequest) =>
{
if (!httpRequest.Headers.ContainsKey("X-Forwarded-Host")) return;
var serverUrl = $"{httpRequest.Headers["X-Forwarded-Proto"]}://" +
$"{httpRequest.Headers["X-Forwarded-Host"]}/" +
$"{httpRequest.Headers["X-Forwarded-Prefix"]}";
swaggerDoc.Servers = new List<OpenApiServer>()
{
new OpenApiServer { Url = serverUrl }
};
});
});
@domaindrivendev , I'm new to this space and unfamiliar with the changes you made to fix this issue. Can you give a brief description on how to use the headers that are now being populated by Swagger? For my use case, I've got an nginx reverse proxy configured like this:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://<server_name>:<port_number>;
}
}
and a kubernetes ingress controller routing traffic down to each pod. The URL looks like this: http://<cluster_name>/<service_name>/Swagger/index.html , the
The swagger/index.html page loads just fine, but the Execute button on an API call fails because of the reverse proxy. I'm not sure how to use the headers to populate the request appropriately. Any help would be much appreciated!
@DanSibbernsen, from 6.1.0, behind a reverse proxy I think you should do something like:
services.Configure<SwaggerOptions>(options => options.PreSerializeFilters.Add((doc, request) =>
{
// [...] update doc.Servers with correct front side URL (can be relative from Swagger)
}));
You should probably open a new issue if not resolved.
Most helpful comment
@rob893 I'm going to add automatic support for detecting the origin url based on some common reverse proxy headers (
X-Forward-*) and this should solve the reverse proxy problem for most cases. In the meantime OR if you need to customize for non-standard proxy headers you can do so by enriching the generated Swagger/OpenAPI document before it's serialized. For example ...