新版本 Swashbuckle swagger 组件中的 坑
新版本 Swashbuckle swagger 组件中的 Servers 坑
Intro
上周做了公司的项目升级,从 2.2 更新到 3.1, swagger 直接更新到了最新,swagger 用的组件是 Swashbuckle.AspNetCore
,然后遇到一个 swagger 的问题, 在本地测试是没问题的,但是部署在测试环境之后就会有问题,主要是 swagger 界面会多一个 servers 的选项,可能会导致 swagger 不能正常使用,下面详细介绍一下
Swagger "bug" reproduce
大概的问题是这样的,在本地环境是好的,在测试环境部署是有问题,测试环境部署之后的 swagger 界面大致如下:
很明显这个 servers 是有问题的,我们实际访问的地址是 https://testserver/swagger
这样的地址,但是 swagger 内部拼出来的 server 地址和实际访问的地址是不符的,swagger 生成的 open api 文档里也会有一个 servers 的属性,示例如下:
这会导致我们使用 swagger 调试 API 的时候会走一个错误的 server 地址,实际请求的地址是 sever 地址加上 api path,可以看一个示例
Dig the Source
Swashbuckle.AspNetCore
是开源的,我们就是扒一扒它的实现源码吧,我们用的是 5.6.3 版本,直接看 5.6.3 tag 对应的代码,可以找到 swagger 的中间件
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/v5.6.3/src/Swashbuckle.AspNetCore.Swagger/SwaggerMiddleware.cs
在这里我们可以看到,再返回给客户端之前 open api 文档响应之前我们是可以看到,是会经过 PreSerializeFilters
处理的,我们再详细看一下 swaggerProvider.GetSwagger
的实现
实现代码在这里(可以通过服务注册找到对应的实现,也可以直接找对应接口的实现)
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/v5.6.3/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs#L31
二者结合来看,servers 会根据用户请求来获取一个 server 地址,而当有 X-Forwarded-Host
请求头的时候如果没有按照 swagger 指定的规则这样进行请求头的转发就会导致有问题,而我们的测试环境也正是因为如此,测试环境有一层 LB,经过 LB 转发了 X-Forwarded-Host
和 X-Forwarded-Proto
请求头,但是没有转发 X-Forwarded-Port
所以经过 swagger 的处理之后,就从 https://testserver
变成了 https://testserver:80
这样
private string GetHostOrNullFromRequest(HttpRequest request)
{if (!request.Headers.TryGetValue("X-Forwarded-Host", out StringValues forwardedHost))return null;var hostBuilder = new UriBuilder($"http://{forwardedHost[0]}");if (request.Headers.TryGetValue("X-Forwarded-Proto", out StringValues forwardedProto))hostBuilder.Scheme = forwardedProto[0];if (request.Headers.TryGetValue("X-Forwarded-Port", out StringValues forwardedPort))hostBuilder.Port = int.Parse(forwardedPort[0]);return hostBuilder.Uri.ToString().Trim('/');
}private string GetBasePathOrNullFromRequest(HttpRequest request)
{var pathBuilder = new StringBuilder();if (request.Headers.TryGetValue("X-Forwarded-Prefix", out StringValues forwardedPrefix))pathBuilder.Append(forwardedPrefix[0].TrimEnd('/'));if (request.PathBase.HasValue)pathBuilder.Append(request.PathBase.Value.TrimEnd('/'));return (pathBuilder.Length > 0)? pathBuilder.ToString(): null;
}
解决方案
从上面的源码中基本就可以分析出问题的原因来,解决的办法我觉得有下面几种:
LB 转发的时候带上
X-Forwarded-Port
请求头,转发原始请求的端口号(需要 LB 转发自己能够控制,我们如果要配置还需要让 DevOps 的童鞋帮忙弄,如果完全是自己控制的就比较方便【推荐】)在使用 Swagger 中间件之前把
X-Forwarded-Port
请求头设置为443
(不够灵活,如果访问 LB 是 http 或者有特别的端口号就会有问题)在使用 swagger 中间件之前把
X-Forwarded-Host
请求头移除掉,这样就不会有 servers 这个属性了(感觉不够优雅)注册一个
PreSerializeFilter
把 Servers 清空,实现代码如下(【推荐】,没有 servers 属性的时候完全按请求 swagger 的 baseUrl 来作为 api 的前缀,示例代码如下)
app.UseSwagger(c =>
{c.PreSerializeFilters.Add((doc, _) =>{doc.Servers?.Clear();});
});
更新之后就没有 servers 属性了,和之前的版本保持一致了
More
我们使用的是 5.6.3 版本,应该从 5.6.0 开始都有这个问题,如果遇到了这个问题不要慌哈,参考上面的解决方案即可
我觉得 swagger 这样的实现方式不太友好,更好的实现应该结合微软的 ForwardHeaders
中间件来实现,Swagger 组件作者表示已经有计划,打算在 6.0 的时候更新结合微软的中间件来实现,详细可以参考 Github 上的 Issue https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1814
Reference
https://github.com/domaindrivendev/Swashbuckle.AspNetCore
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/v5.6.3/src/Swashbuckle.AspNetCore.Swagger/SwaggerMiddleware.cs
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/v5.6.3/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs#L31
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1814
新版本 Swashbuckle swagger 组件中的 坑相关推荐
- vue中父子组件通信的坑
转自:https://www.cnblogs.com/goloving/p/8660407.html 当在一个组件中,使用了其他自定义组件时,就会利用子组件的属性和事件来和父组件进行数据交流. 父子组 ...
- vue爬坑之 父组件向子组件异步传参 子组件中拿不到值的解决方法
做项目时候遇到一件怪事: 父组件向子组件<dialog-info/>传个参数arrdata,是个数组 因为是Array类型的参数,子组件中进行了接收,并且default通过函数返回一个空数 ...
- (四)Asp.net web api中的坑-【api的返回值】
(四)Asp.net web api中的坑-[api的返回值] 原文:(四)Asp.net web api中的坑-[api的返回值] void无返回值 IHttpActionResult HttpRe ...
- ios navigation的返回按钮长按_Android Jetpack架构组件 — Navigation入坑详解 [转]
前言 这是最近看见的觉得比较有意思的文,希望对大家的学习有帮助. Navigation 直接翻译即为导航,它是 Android Jetpack 组件之一,让单 Activity 应用成为首选架构.应用 ...
- element-ui表格组件table踩坑总结
table组件中,基本情况简述: element框架的table组件,内容涵盖以下总结知识点,内容比较基础,知识有点交叉.对比学习更易于理解.应用和掌握. 常用UI效果,参考点: table边框设置( ...
- mysql 主从 通俗易懂_MySQL 主从同步架构中你不知道的“坑”(完结篇)
MySQL 主从同步架构中你不知道的"坑"(完结篇) 收录于话题 #MySQL从入门到放弃 26个 点击上方蓝字,关注我们哟! 前言导读 之前写出一篇文章也是关于这个主从同步架构的 ...
- 微信小程序 自定义组件中 triggerEvent() 函数失效的一种情况 (Cannot read property ‘triggerEvent‘ of undefined)
在网络上并没有搜索到这种情况,这里记录下避免以后的自己和广大码农踩到这个坑 问题描述:在自定义组件中想调用 this.triggerEvent()函数给父组件传参,过程中报错:Cannot read ...
- Vue组件中使用canvas实现蜂巢效果的一些尝试
Vue组件中使用canvas实现蜂巢效果的一些尝试 前段时间,看到D3.js的官方网站的蜂巢效果,感觉不错,不过一直没有时间去实际的实现下,借这次机会,算是填了前面的坑~~,先来看看d3.js的效 ...
- Vue3.x 父组件Setup、Ref操纵子组件中的元素方法
目录 父组件 方法一: defineComponent 方法二: setup语法糖 小伙伴们在开箱Vue3的过程中一点会踩到不少坑. 比如很多小伙伴想要通过ref来操纵DOM,可偏偏翻车. 这里分享两 ...
最新文章
- 计算机考研数学试卷类型,数学会是你的计算机考研拦路虎吗?
- Linux 中的驱动开发的初学者体会
- 简析Visual C++中的活动数据对象
- 缺少Python27_d.lib的解决方法
- 手机上调试html,在手机上打印调试信息 – debug.js
- Ueditor、FCKeditor、Kindeditor编辑器漏洞
- 2018美赛C题翻译
- 10G网络布线方案有多少种?
- 学习爬虫的第三天 (bs4 \ urllib \ xlwt \ re 的练习爬取豆瓣top250保存成excel格式)
- Cocos2d-x CocosBuilder使用教程(一)HelloCocosBuilder
- 开源众包-项目大厅数据爬取
- [zz] 三维动画软件Maya
- SpringBoot (八)日志配置
- Jenkins自动化打包生成二维码下载链接
- 奇数阶魔方阵算法分析
- ACL 2021 | 基于词依存信息类型映射记忆神经网络的关系抽取
- 大学计算机引论作业,计算机引论-1计算引论-认识计算机.pdf
- fest + selenium进行In-browser Applet自动化测试
- 琴伤+园游会+迷迭香+美人鱼+上海一九四三+威廉古堡+最后的战役+她的睫毛+麦芽糖
- 互联网校招关于offer的抉择及自己的一些感悟