Search code examples
asp.net-coreswaggerasp.net-core-webapiswagger-uiswashbuckle

Swashbuckle using port 80 for https when run behind reverse proxy


I have a .net core api documented with swagger/swashbuckle.

When running the swagger ui on localhost on url https://localhost:44390/ the "Try it out" works fine.

We have the same solution in an App service in Azure with an Azure Front Door acting as reverse proxy. Front Door only accepts https traffic and only forwards https traffic. Front door domain is widget.example.com and App service is widget-test-app.azurewebsites.net. When running the swagger ui in Azure using the url https://widget.example.com/api/index.html there are two differences compared to running in localhost:

  1. The swagger ui is showing a Servers -heading and a dropdown
  2. The swagger ui is showing the server url as https://widget.example.com:80

I added an endpoint in the api with the following code

return $"Host {HttpContext.Request.Host.Host} Port {HttpContext.Request.Host.Port} Https {HttpContext.Request.IsHttps}";

When requesting https://widget.example.com/api/v1/test/url it returns

Host widget-test-app.azurewebsites.net Port Https True

This is completely ok since Front door is changing the host header. Port is empty, though.

Summary: Swagger ui is showing the correct domain in the Servers -dropdown but the port number is wrong. How can I get it to either omit the port number if it's 80 or 443, or add it correctly?

Update: The problem is in the swagger.json file which behind the reverse proxy includes a servers element

"servers": [{
  "url": "https://widget.example.com:80"
}]

Startup.ConfigureServices

services.AddApiVersioning(options => {
  options.Conventions.Add(new VersionByNamespaceConvention());
});

services.AddVersionedApiExplorer(o => {
  o.GroupNameFormat = "'v'VVV";
  o.SubstituteApiVersionInUrl = true;
});

services.AddSwaggerGen(c => {
  c.SwaggerDoc("v1", new OpenApiInfo {
    Title = "Widget backend v1", Version = "v1"
  });
  c.SwaggerDoc("v2", new OpenApiInfo {
    Title = "Widget backend v2", Version = "v2"
  });
  c.EnableAnnotations();
  c.AddEnumsWithValuesFixFilters();

  var xmlFile = $ "{Assembly.GetExecutingAssembly().GetName().Name}.xml";
  var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
  c.IncludeXmlComments(xmlPath);
});

Startup.Configure

app.UseSwagger(options => {
  options.RouteTemplate = "/api/swagger/{documentname}/swagger.json";
});

app.UseSwaggerUI(options => {
  foreach(var description in provider.ApiVersionDescriptions) {
    options.SwaggerEndpoint($ "/api/swagger/{description.GroupName}/swagger.json", "widget backend " + description.GroupName);
  }
  options.RoutePrefix = "api";
});

Solution

  • To fix this I cleared the Servers -list. Here is my code:

    app.UseSwagger(options =>
    {
        options.RouteTemplate = "/api/swagger/{documentname}/swagger.json";
        options.PreSerializeFilters.Add((swagger, httpReq) =>
        {
            //Clear servers -element in swagger.json because it got the wrong port when hosted behind reverse proxy
            swagger.Servers.Clear();
        });
    });