In a reverse-proxy environment, the base path can often include multiple segments:
https://myapi.com/some/root/path
The correct way to set up custom base paths is to use app.UsePathBase:
```c#
// in Startup.Configure
public void Configure(IApplicationBuilder app) {
app.UsePathBase("/some/root/path");
}
When you do this, your new "application root" path is the above path. Any place you use `~/` in your paths will add that request base path. When using IIS integration, this is all taken care of for you:
https://github.com/aspnet/AspNetCore/blob/master/src/Servers/IIS/IISIntegration/src/WebHostBuilderIISExtensions.cs#L43
I found, however, that not all pieces in the `SwaggerUI` support these alternate application roots.
If you do this:
```c#
app.UsePathBase("/some/root/path");
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("swagger/v1/swagger.json", "My API V1");
});
Then my swagger JSON is correctly served by /some/root/path/swagger/v1/swagger.json and the UI is served at /some/root/path/swagger/index.html.
However, it can't find the swagger JSON off the relative path. It assumes a relative path off of the current UI /some/root/path/swagger/swagger/v1/swagger.json.
The only way I can get this to work is manually include the root path in the URLs:
```c#
app.UsePathBase("/some/root/path");
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("/some/root/path/swagger/v1/swagger.json", "My API V1");
});
If my application's path base is set, then *everything* should work seamlessly, I shouldn't need to configure anything. All the middleware does is alter the `Request.BasePath` part. Additionally, that root path could come in from configuration somewhere, and I don't want to have my Swagger UI aware of this.
Ideally, I could use root-relative paths:
```c#
app.UsePathBase("/some/root/path");
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("~/swagger/v1/swagger.json", "My API V1");
});
This doesn't work, however, as the URL requested becomes:
/some/root/path/swagger/~/swagger/v1/swagger.json.
Note that I do not need to specify the RoutePrefix, since that part does respect the request base path.
The path that you provide to SwaggerEndpoint is relative to the Swagger UI page. Therefore, you _should_ be able to make the whole setup proxy / virtual path agnostic with the following configuration:
app.UsePathBase("/some/root/path");
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("v1/swagger.json", "My API V1");
});
Perfect, thanks!
@domaindrivendev how would I be able to apply the same logic for defining a OpenApiServer that should be dependant of a relative path (because of the reverse proxy) ?
@diogonborges see https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1298#issuecomment-620269062
I tried this but the swagger.json is not served on the relative path.
app.UsePathBase("/some/root/path");
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("api/swagger.json", "My API V1");
});
Then my swagger JSON is served by /swagger/api/swagger.json and not the relative path. And the UI is served at /some/root/path/swagger/index.html, complaining about
Fetch error Internal Server Error http://localhost:10680/some/root/path/swagger/api/swagger.json
This is in a WebApi inside a ServiceFabric cluster with kestrel. How can I correctly add the basePath to swagger?
using Swashbuckle.AspNetCore v 5.4.1
using .net core 3.1
Same question also asked here, just with different setup tried https://stackoverflow.com/questions/61733433/how-do-i-setup-swashbucle-v5-with-swagger-when-i-have-a-custom-base-url
I added the PreSerializeFilter from #1298 (comment)
if (!httpReq.Headers.ContainsKey("X-Original-Host")) return;
var serverUrl = $"{httpReq.Headers["X-Original-Proto"]}://" +
$"{httpReq.Headers["X-Original-Host"]}/" +
$"{httpReq.Headers["X-Original-Prefix"]}";
swaggerDoc.Servers = new List<OpenApiServer>()
{
new OpenApiServer { Url = serverUrl }
};
This helps in that the swagger.json is now loaded correctly at: /some/root/path/swagger/api/swagger.json
But when i try out an endpoint from the Swagger UI the curl url does not have the relative basePath. It goes to http://X.X.X.X/path , missing the basePath in it.
I added the PreSerializeFilter from #1298 (comment)
if (!httpReq.Headers.ContainsKey("X-Original-Host")) return; var serverUrl = $"{httpReq.Headers["X-Original-Proto"]}://" + $"{httpReq.Headers["X-Original-Host"]}/" + $"{httpReq.Headers["X-Original-Prefix"]}"; swaggerDoc.Servers = new List<OpenApiServer>() { new OpenApiServer { Url = serverUrl } };This helps in that the swagger.json is now loaded correctly at: /some/root/path/swagger/api/swagger.json
But when i try out an endpoint from the Swagger UI the curl url does not have the relative basePath. It goes to http://X.X.X.X/path , missing the basePath in it.
Did you find how to generate the Try Out endpoint correctly?. I am having the same issues and I am not sure how to solve it
No. This is still an unresolved problem. :-/
@lisamariet the original issue here was resolved and closed by the submitter. If you have a separate (albeit related) problem, please create a new issue for it, providing clear repro steps. Thanks
use "../"
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("../swagger/v1/swagger.json", "My API V1");
});
IMO no web application should care what it's final external path is. It should always work relative to itself and never assume that / is the root. The reason is that an app should work in front of and behind a reverse proxy. The suggestions above (UsePathBase) mean swagger will ONLY work behind a reverse proxy. I am pretty sure if Swagger is careful with paths (never referencing / but only ./) this should not be a problem.
Alternatively swagger should detect (in the browser) that, although it's been configured to serve /api/ internally it has been externally started from /extpath/api/ and work accordingly.
This is still a problem. And it doesn't work the way @domaindrivendev described. Why was this closed I wouldn't know but it shouldn't have been. I'm experiencing the exact same problem when using a subapplication within IIS site.
It was closed by the original submitter and therefore the problem , as defined by them, IS resolved. As I said above, if something related is not working for you, please create a separate issue and (most importantly) create a minimal app (i.e. starting from blank project) that reproduce the issue, and post to GitHub where I can pull down and troubleshoot
Most helpful comment
IMO no web application should care what it's final external path is. It should always work relative to itself and never assume that / is the root. The reason is that an app should work in front of and behind a reverse proxy. The suggestions above (UsePathBase) mean swagger will ONLY work behind a reverse proxy. I am pretty sure if Swagger is careful with paths (never referencing
/but only./) this should not be a problem.Alternatively swagger should detect (in the browser) that, although it's been configured to serve
/api/internally it has been externally started from/extpath/api/and work accordingly.