日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

新版本 Swashbuckle swagger 组件中的 坑

發(fā)布時間:2023/12/4 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 新版本 Swashbuckle swagger 组件中的 坑 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

新版本 Swashbuckle swagger 組件中的 Servers 坑

Intro

上周做了公司的項目升級,從 2.2 更新到 3.1, swagger 直接更新到了最新,swagger 用的組件是 Swashbuckle.AspNetCore,然后遇到一個 swagger 的問題, 在本地測試是沒問題的,但是部署在測試環(huán)境之后就會有問題,主要是 swagger 界面會多一個 servers 的選項,可能會導(dǎo)致 swagger 不能正常使用,下面詳細介紹一下

Swagger "bug" reproduce

大概的問題是這樣的,在本地環(huán)境是好的,在測試環(huán)境部署是有問題,測試環(huán)境部署之后的 swagger 界面大致如下:

很明顯這個 servers 是有問題的,我們實際訪問的地址是 https://testserver/swagger 這樣的地址,但是 swagger 內(nèi)部拼出來的 server 地址和實際訪問的地址是不符的,swagger 生成的 open api 文檔里也會有一個 servers 的屬性,示例如下:

這會導(dǎo)致我們使用 swagger 調(diào)試 API 的時候會走一個錯誤的 server 地址,實際請求的地址是 sever 地址加上 api path,可以看一個示例

Dig the Source

Swashbuckle.AspNetCore 是開源的,我們就是扒一扒它的實現(xiàn)源碼吧,我們用的是 5.6.3 版本,直接看 5.6.3 tag 對應(yīng)的代碼,可以找到 swagger 的中間件

https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/v5.6.3/src/Swashbuckle.AspNetCore.Swagger/SwaggerMiddleware.cs

在這里我們可以看到,再返回給客戶端之前 open api 文檔響應(yīng)之前我們是可以看到,是會經(jīng)過 PreSerializeFilters 處理的,我們再詳細看一下 swaggerProvider.GetSwagger 的實現(xiàn)

實現(xiàn)代碼在這里(可以通過服務(wù)注冊找到對應(yīng)的實現(xiàn),也可以直接找對應(yīng)接口的實現(xiàn))

https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/v5.6.3/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs#L31

二者結(jié)合來看,servers 會根據(jù)用戶請求來獲取一個 server 地址,而當有 X-Forwarded-Host 請求頭的時候如果沒有按照 swagger 指定的規(guī)則這樣進行請求頭的轉(zhuǎn)發(fā)就會導(dǎo)致有問題,而我們的測試環(huán)境也正是因為如此,測試環(huán)境有一層 LB,經(jīng)過 LB 轉(zhuǎn)發(fā)了 X-Forwarded-Host 和 X-Forwarded-Proto 請求頭,但是沒有轉(zhuǎn)發(fā) X-Forwarded-Port 所以經(jīng)過 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 轉(zhuǎn)發(fā)的時候帶上 X-Forwarded-Port 請求頭,轉(zhuǎn)發(fā)原始請求的端口號(需要 LB 轉(zhuǎn)發(fā)自己能夠控制,我們?nèi)绻渲眠€需要讓 DevOps 的童鞋幫忙弄,如果完全是自己控制的就比較方便【推薦】)

  • 在使用 Swagger 中間件之前把 X-Forwarded-Port 請求頭設(shè)置為 443(不夠靈活,如果訪問 LB 是 http 或者有特別的端口號就會有問題)

  • 在使用 swagger 中間件之前把 X-Forwarded-Host 請求頭移除掉,這樣就不會有 servers 這個屬性了(感覺不夠優(yōu)雅)

  • 注冊一個 PreSerializeFilter 把 Servers 清空,實現(xiàn)代碼如下(【推薦】,沒有 servers 屬性的時候完全按請求 swagger 的 baseUrl 來作為 api 的前綴,示例代碼如下)

  • app.UseSwagger(c?=> {c.PreSerializeFilters.Add((doc,?_)?=>{doc.Servers?.Clear();}); });

    更新之后就沒有 servers 屬性了,和之前的版本保持一致了

    More

    我們使用的是 5.6.3 版本,應(yīng)該從 5.6.0 開始都有這個問題,如果遇到了這個問題不要慌哈,參考上面的解決方案即可

    我覺得 swagger 這樣的實現(xiàn)方式不太友好,更好的實現(xiàn)應(yīng)該結(jié)合微軟的 ForwardHeaders 中間件來實現(xiàn),Swagger 組件作者表示已經(jīng)有計劃,打算在 6.0 的時候更新結(jié)合微軟的中間件來實現(xiàn),詳細可以參考 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

    總結(jié)

    以上是生活随笔為你收集整理的新版本 Swashbuckle swagger 组件中的 坑的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。