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

Swagger UI not working while API service behind reverse proxy #1892

Closed
OculiViridi opened this issue Jan 17, 2019 · 7 comments
Closed

Swagger UI not working while API service behind reverse proxy #1892

OculiViridi opened this issue Jan 17, 2019 · 7 comments

Comments

@OculiViridi
Copy link

With reference to #1717, I need some help about configuration of Swagger when using API behind a reverse proxy. In this case the reverse proxy should be IIS. But I also want to know if and what are the possible differences to take into account if I change the proxy server.

Right now I'm using this configuration:

public static void UseSwaggerWithConfiguration(this IApplicationBuilder app)
{
    app.UseSwagger(config =>
    {
        config.PostProcess = (document, request) =>
        {
            if (request.Headers.ContainsKey("X-Forwarded-Host"))
            {
                document.Host = request.Headers["X-Forwarded-Host"].First();
				// This line was commented because of there's no X-...-Path header on IIS...
                //document.BasePath = request.Headers["X-External-Path"].First();
            }
        };
    });

    app.UseSwaggerUi3(config =>
    {
        config.OAuth2Client = new OAuth2ClientSettings
        {
            ClientId = "control-api-swagger",
            ClientSecret = "1B746C9D-4E00-449C-B3F2-A17171B6B46E".ToSha256(),
            AppName = $"{title} - Swagger"
        };

        config.TransformToExternalPath = (internalUiRoute, request) =>
        {
			// What should be done here?
            var externalPath = request.Headers.ContainsKey("X-External-Path") ? request.Headers["X-External-Path"].First() : "";
            return externalPath + internalUiRoute;
        };

        config.SwaggerRoutes.Add(new SwaggerUi3Route("v1.0", "/swagger/v1.0/swagger.json"));
    });
}

And I'm getting this problem:

image

But, when used without proxy, everything works.

As @deepforest was suggesting in #1717:

Based on MDN, X-Forwarded-Host is a de-facto standard XFH header, identifying the original host, useful to determine which Host was originally used.
So based on @RSuter nginx conf file, you can replace X-External-Host with X-Forwarded-Host.
As for the X-External-Path, if you consider the X-Forwarded-Host to also contain the path: '/externalpath', then you can also omit X-External-Path, but then, it will be a bit "harder" to extract the path in the Startup.cs file, unless @RSuter will update the TransformToExternalPath config to accept only the Host, and do the magic inside.

What should I do to make it works?

@StasPerekrestov
Copy link
Contributor

I'm looking at SwaggerDocumentMiddleware. It looks like GenerateSwaggerAsync caches generated _swaggerJson document. The issue is that when an application is deployed behind a reverse-proxy, e.g. nginx, uses the PostProcess handler to override host/basePath properties and the application is also accessible from the internal network, then the cached JSON document works either from public or internal network. In other words, if somebody accesses (performs the first HTTP request) the application from the internal network, then it won't work from the public network and vice versa.

What if to store _swaggerJson in a sort of dictionary, e.g.

// pseudo code
class Key {
  string host;
  string basePath;
}
Dictionary<Key, Json> _cache;

?

This approach allows to workaround the issue without much refactoring.

@RicoSuter

@RicoSuter
Copy link
Owner

@StasPerekrestov looks fine to me... so this would be needed if the swagger ui is exposed on two different urls?

@StasPerekrestov
Copy link
Contributor

@RicoSuter exactly. I'll prepare a pull request and create a separate issue.
Thanks.

@OculiViridi
Copy link
Author

@StasPerekrestov, @RicoSuter I'm having the same issue since about 3 months.
I'm still in beta development with my application and so I was waiting to open the issue.

The problem for me is that when I install my server application on our test server, if I open the API from localhost/..., then Swagger is not working anymore from the external IP of the server, because the reference on the BasePath is cached as localhost/.... The only solution is to reboot my server application.

@RicoSuter
Copy link
Owner

Please review this PR: #2196

@jeremyVignelles
Copy link
Collaborator

The PR has been merged, why is this still open?

@RicoSuter
Copy link
Owner

Let's close...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants