当我有自定义基本网址时,如何使用 swagger 设置 Swashbuckle v5? [英] How do I setup Swashbuckle v5 with swagger when I have a custom base url?

查看:9
本文介绍了当我有自定义基本网址时,如何使用 swagger 设置 Swashbuckle v5?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 .net API 升级到 .net Core 3.1 并使用 Swashbuckle.AspNetcore 5.4.1.API 在 ServiceFabric 应用程序中运行.我发现了这个 https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1173 并尝试遵循并生成 swagger 但如果我尝试使用 Swagger UI 发送请求,则请求 URL 的 IP 错误,因此请求失败.在旧的 Swashbuckle 4.0.1 设置中,我们没有指定主机,只有相对的 basePath.我怎样才能达到同样的效果?

I am upgrading a .net API to .net Core 3.1 and using Swashbuckle.AspNetcore 5.4.1. The API is running inside a ServiceFabric app. I found this https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1173 and tried to follow that and swagger gets generated but if I try to use the Swagger UI to send requests the request URL is with the wrong IP so the request fail. In the old Swashbuckle 4.0.1 setup we did not specify host, only the relative basePath. How can I achieve the same?

Startup.cs

var swaggerBasePath = "/MySfApp/SfApp.ClientApi/";

app.UseSwagger(c =>
{
    c.SerializeAsV2 = serializeAsSwaggerV2;
    
    c.RouteTemplate = "swagger/{documentName}/swagger.json";
    c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
    {
        swaggerDoc.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}{swaggerBasePath}" } };
    });
});

app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("api/swagger.json", "My API V1");
});

结果是 Swagger UI 在 URL 上正确加载:

The result is that the Swagger UI loads correctly on URL:

http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/index.html

它在名称下说 BaseUrl 是:

and it says under name that BaseUrl is:

[ Base URL: 10.0.0.4:10680/MySfApp/SfApp.ClientApi/ ]

10.0.0.4:10680 是 ServiceFabric 集群内的节点.从外部访问的正确 IP 是 145.12.23.1:54000.在 Swashbuckle 的旧版本 (4.0.1) 中,它首先显示没有 IP 的 baseUrl:/MySfApp/SfApp.ClientApi"

The 10.0.0.4:10680 is the node inside the ServiceFabric cluster. Correct IP to reach from outside is 145.12.23.1:54000. In the older version (4.0.1) of Swashbuckle it says baseUrl without IP first: "/MySfApp/SfApp.ClientApi"

Swagger.json 位于:

Swagger.json is located at:

http://40.68.213.118:19081/MySfApp/SfApp.ClientApi/swagger/api/swagger.json

它说:

"swagger": "2.0",
... 
"host": "10.0.0.4:10680",  
"basePath": "/MySfApp/SfApp.ClientApi/",
"schemes": [
"http"
],
"paths": {
"/activity/{activityId}": {
"get"
...etc

如果我尝试从 Swagger UI 发送 GET 请求,则会将请求发送到错误的 IP:

If i try to send a GET request from the Swagger UI the request is sent to wrong IP:

curl -X GET "http://10.0.0.4:10680/MySfApp/MySfApp/activity/3443"


编辑 1:经过一番挖掘后,我现在将设置更改为启动.cs


EDIT 1: After some digging I have now changed the setup to this in startup.cs

var swaggerBasePath = "/MySfApp/SfApp.ClientApi/";
app.UsePathBase($"/{swaggerBasePath}");
app.UseMvc();
app.UseSwagger(c =>
{
    c.SerializeAsV2 = serializeAsSwaggerV2;

    c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
    {
        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 }
        };
    });
});
app.UseSwaggerUI(options => {
    options.SwaggerEndpoint("api/swagger.json", "My API V1");
});

这会导致 Swagger UI 使用 baseUrl 正确加载

This now leads to the Swagger UI loading properly with the baseUrl

http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/index.html

而且 swagger.json 也使用正确的 baseUrl 正确提供.

and also swagger.json is served correctly with the correct baseUrl.

http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/api/swagger.json

所以错误的主机名被解析.感谢这个帖子的想法.

So the wrong hostname is resolved. Thanks to idea from this thread.

但是,当我尝试从 Swagger UI 页面调用端点时,curl URL 不包含 baseUrl.如此接近……但目前无法使用 Swagger UI.

However when I try to call an endpoint from the Swagger UI page, the curl URL does not include the baseUrl. So closer... but currently not possible to use Swagger UI.

curl -X GET "http://10.0.0.4:10680/activity/3443"

swagger.json 没有定义host"和basePath".

The swagger.json does not have 'host' nor 'basePath' defined.

推荐答案

我们使用的是 Swashbuckle 版本 6.1.4 - 这是撰写本文时的最新版本,我们仍在使用当我们的 API 部署在通过 Azure Front Door 和 APIM 映射的 Azure App Service 中时,同样的问题.试一试"功能不起作用,因为从 Swagger UI 中剥离了基本路径/api 路由前缀.例如,

We're using Swashbuckle version 6.1.4 - which is the latest as of this time of writing and we're still having the same issue when our API is deployed in Azure App Service that is mapped through Azure Front Door and APIM. The "Try out" functionality does not work as the base path / api route prefix is stripped from the Swagger UI. For example,

Swagger UI 使用的是 https://{DOMAIN}.com/{BASEPATH}/v1/Foo 而不是 https://{DOMAIN}.com/v1/Foo.可以看到 /BASEPATH 不见了.

Instead of https://{DOMAIN}.com/{BASEPATH}/v1/Foo, the Swagger UI uses this: https://{DOMAIN}.com/v1/Foo. You can see that the /BASEPATH is missing.

我花了一整天的时间试图通过反复试验来解决这个问题,尝试了各种方法但没有运气,我无法从 swagger 配置中获得基本路径的优雅方法.目前,这是我修复它的方法:

I spent the whole day trying to fix this with trial and error, trying various approaches with no luck, I couldn't get an elegant way to get the base path from swagger configuration. For the time being, here's what I did to fix it:

app.UseSwagger(options =>
{
    //Workaround to use the Swagger UI "Try Out" functionality when deployed behind a reverse proxy (APIM) with API prefix /sub context configured
    options.PreSerializeFilters.Add((swagger, httpReq) =>
    {
         if (httpReq.Headers.ContainsKey("X-Forwarded-Host"))
         {
            //The httpReq.PathBase and httpReq.Headers["X-Forwarded-Prefix"] is what we need to get the base path.
            //For some reason, they returning as null/blank. Perhaps this has something to do with how the proxy is configured which we don't have control.
            //For the time being, the base path is manually set here that corresponds to the APIM API Url Prefix.
            //In this case we set it to 'sample-app'. 
    
            var basePath = "sample-app"
            var serverUrl = $"{httpReq.Scheme}://{httpReq.Headers["X-Forwarded-Host"]}/{basePath}";
            swagger.Servers = new List<OpenApiServer> { new OpenApiServer { Url = serverUrl } };
         }
    });
})
.UseSwaggerUI(options =>
{
    options.RoutePrefix = string.Empty;
    options.SwaggerEndpoint("swagger/v1/swagger.json", "My Api (v1)");
});

这里是与此问题相关的公开讨论这里.

Here's an open discussion related to this issue here.

这篇关于当我有自定义基本网址时,如何使用 swagger 设置 Swashbuckle v5?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆