如何让 Swagger UI 将端口 443 与 Swashbuckle 一起使用?

How do I get Swagger UI to use port 443 with Swashbuckle?

在我们的 运行 我们的 RESTful Web 服务的 QA 和 Prod 环境中,端口 80 未打开。所以目前当我尝试在 QA 中使用 Swagger UI 时,我收到这条消息并且它只是挂起:

fetching resource list: http://qa-server:80/product-catalog-api/swagger/docs/v1; Please wait.

我正在使用 Swashbuckle 配置 Swagger。我也在配置中更改了这一行,但它仍然不起作用。

// If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access
// the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
// about them, you can use the "Schemes" option as shown below.
//
c.Schemes(new[] { "https" });

SSL 端口 443 是开放的所以我想去 Swagger UI 到 运行 就可以了。我可以手动将 http://qa-server:80/product-catalog-api/swagger/docs/v1 更改为 https://qa-server/product-catalog-api/swagger/docs/v1,然后 Swagger 将列出我的 Web 方法,但是当我单击 Try it out! 时它会挂起 这是控制台的输出:SCRIPT5: Access is denied. File: swagger-ui-min-js, Line: 10, Column: 4300

编辑:

所以我一直在深入挖掘,已经走得更远了一点,但仍然不是我想去的地方。如果我在 Swagger index.html 文件上查看源代码,我可以看到问题:

window.swashbuckleConfig = {
  rootUrl: 'http://qa-server:80/product-catalog-api',
  discoveryPaths: arrayFrom('swagger/docs/v1'),
  booleanValues: arrayFrom('true|false'),
  validatorUrl: stringOrNullFrom('null'),
  customScripts: arrayFrom(''),
  docExpansion: 'none',
  oAuth2Enabled: ('false' == 'true'),
  oAuth2ClientId: '',
  oAuth2ClientSecret: '',
  oAuth2Realm: '',
  oAuth2AppName: '',
  oAuth2ScopeSeperator: ' ',
  oAuth2AdditionalQueryStringParams: JSON.parse('{}')
};

即使我以 https 导航到该站点并将 Swashbuckle 方案设置为 https,它仍将 rootUrl 生成为 http。我认为自从我使用 Swashbuckle 以来,我必须使用它来配置 index.html 因为我的代码中没有该文件,所以我猜 Swashbuckle 正在动态生成它。

我确实发现了我在更改 swagger.json 路径时遗漏了什么。它显然需要那里的端口号。因此,如果我导航到 swagger 索引页面并手动将 json 文件的路径更改为 https://qa-server:443/product-catalog-api/swagger/docs/v1 一切正常。所以现在我想我已经将问题归结为如何使用 Swashbuckle 更改 Swaggers index.html 中的 rootUrl。

编辑 2

好吧,我想我已经正确配置了 Swashbuckle,因为它在我们的开发服务器上正确生成了 index.html,但不是 qa 所以我想剩下的问题是由于环境或我的包的一些差异没有在 qa 中正确安装。

发展:

window.swashbuckleConfig = {
  rootUrl: 'https://server-dev:443/product-catalog-api',
  discoveryPaths: arrayFrom('swagger/docs/v1'),
  booleanValues: arrayFrom('true|false'),
  validatorUrl: stringOrNullFrom('null'),
  customScripts: arrayFrom(''),
  docExpansion: 'none',
  oAuth2Enabled: ('false' == 'true'),
  oAuth2ClientId: '',
  oAuth2ClientSecret: '',
  oAuth2Realm: '',
  oAuth2AppName: '',
  oAuth2ScopeSeperator: ' ',
  oAuth2AdditionalQueryStringParams: JSON.parse('{}')
};

质量检查:

window.swashbuckleConfig = {
  rootUrl: 'http://qa-server:80/product-catalog-api',
  discoveryPaths: arrayFrom('swagger/docs/v1'),
  booleanValues: arrayFrom('true|false'),
  validatorUrl: stringOrNullFrom('null'),
  customScripts: arrayFrom(''),
  docExpansion: 'none',
  oAuth2Enabled: ('false' == 'true'),
  oAuth2ClientId: '',
  oAuth2ClientSecret: '',
  oAuth2Realm: '',
  oAuth2AppName: '',
  oAuth2ScopeSeperator: ' ',
  oAuth2AdditionalQueryStringParams: JSON.parse('{}')
};

编辑 3

我们进行了测试以进一步隔离问题。我们的 QA 环境中有一个 A10 负载均衡器。我们为开发环境站了一个新的 A10 看看发生了什么,我们现在在开发中遇到了同样的问题。 A10 正在执行一些我们删除的 http header 操作以查看是否是问题所在,但仍然得到相同的结果。我相信通过服务器的设置方式,SSL 被卸载到 A10 并且盒子实际上 运行ning 我的代码正在获取 http。所以当 Swashbuckle 代码 运行s 时,它是 http 下的 运行ning 引起的问题。我想我需要一种方法来强制它始终为 https。

当 HTTP 请求到达 swagger/docs/v1swagger/ui/index 时,Swashbuckle 会为您生成 Swagger 文档。如果您的请求通过 https 传入,那么它生成的默认 index.html 将包含 rootUrlhttps://yourdomain:443/yourapiapplication。同样,如果它通过 http 进入,则 rootUrl 将是 http://yourdomain:80/yourapiapplication。鉴于这种情况,您的问题的主要候选者是缓存。您是否通过覆盖 SwaggerConfig.cs 中的默认 swagger 提供程序启用了 Swagger 文档的缓存?或者您的 QA 环境是否具有与您的开发环境不同的代理服务器或缓存设置?通过 HTTPS 向您的 QA 服务器发出新请求重新生成文档应该会在您的 index.html.

中生成正确的 rootUrl

我终于明白了!感谢 Sampada 和 strick01 帮助我隔离问题。我在 github 上找到了这篇文章,其中包含使用 Swashbuckle 强制 https 的解决方案:

https://github.com/domaindrivendev/Swashbuckle/issues/296

config
    .EnableSwagger("docs/{apiVersion}",
    c =>
    {
      ...
      c.RootUrl(ResolveBasePath);
      ...
    })
    .EnableSwaggerUi();

private static string ResolveBasePath(HttpRequestMessage message)
{
    var virtualPathRoot = message.GetRequestContext().VirtualPathRoot;

    var schemeAndHost = "https://" + message.RequestUri.Host;
    return new Uri(new Uri(schemeAndHost, UriKind.Absolute), virtualPathRoot).AbsoluteUri;
}