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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

小心 HttpClient 中的 FormUrlEncodeContent 的 bug

發(fā)布時(shí)間:2023/12/4 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小心 HttpClient 中的 FormUrlEncodeContent 的 bug 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

小心 HttpClient 中的 FormUrlEncodeContent 的 bug

Intro

最近發(fā)現(xiàn)活動(dòng)室預(yù)約項(xiàng)目里的上傳圖片有時(shí)候會(huì)有問(wèn)題,周末找時(shí)間測(cè)試了一下,發(fā)現(xiàn)小圖片的上傳沒(méi)問(wèn)題,大圖片上傳會(huì)有問(wèn)題,而且異常信息還很奇怪,System.UriFormatException: Invalid URI: The Uri string is too long 看這個(gè)錯(cuò)誤的信息還以為是請(qǐng)求的 url 過(guò)長(zhǎng)導(dǎo)致的,但是實(shí)際請(qǐng)求的 url 很短,詭異的異常信息

測(cè)試示例

為了方便大家了解和測(cè)試這個(gè)bug,我在 Github 上提供了一個(gè)示例 https://github.com/WeihanLi/SamplesInPractice/blob/master/HttpClientTest/FormUrlEncodeContentTest.cs

HttpClient 示例代碼:

public class FormUrlEncodeContentTest {private const string TestUrl = "https://cnblogs.com";public static async Task FormUrlEncodedContentLengthTest(){using (var httpClient = new HttpClient(new NoProxyHttpClientHandler())){using (var response = await httpClient.PostAsync(TestUrl, new FormUrlEncodedContent(new Dictionary<string, string>(){{"bigContent", new string('a', 65535)},}))){Console.WriteLine($"response status code:{response.StatusCode}");}}}public static async Task ByteArrayContentLengthTest(){using (var httpClient = new HttpClient(new NoProxyHttpClientHandler())){var postContent = $"bigContent={new string('a', 65535)}";using (var response = await httpClient.PostAsync(TestUrl, new ByteArrayContent(postContent.GetBytes()))){Console.WriteLine($"response status code:{response.StatusCode}");}}}public static async Task StringContentLengthTest(){using (var httpClient = new HttpClient(new NoProxyHttpClientHandler())){var postContent = $"bigContent={new string('a', 65535)}";using (var response = await httpClient.PostAsync(TestUrl, new StringContent(postContent))){Console.WriteLine($"response status code:{response.StatusCode}");}}} }

測(cè)試代碼:

InvokeHelper.OnInvokeException = Console.WriteLine;await InvokeHelper.TryInvokeAsync(FormUrlEncodeContentTest.FormUrlEncodedContentLengthTest); Console.WriteLine(); await InvokeHelper.TryInvokeAsync(FormUrlEncodeContentTest.StringContentLengthTest); Console.WriteLine(); await InvokeHelper.TryInvokeAsync(FormUrlEncodeContentTest.ByteArrayContentLengthTest);Console.WriteLine("Completed!");

輸出結(jié)果如下:

揪出異常始末

上傳圖片的時(shí)候會(huì)調(diào)用一個(gè)碼云的一個(gè) POST 接口來(lái)保存上傳的圖片,參數(shù)是通過(guò) form-data 的方式傳遞的,在 POST 的時(shí)候報(bào)異常了,異常信息很詭異,具體信息和上面的是一樣的:

這個(gè)異常信息看上去像是 url 過(guò)長(zhǎng)導(dǎo)致的,但是實(shí)際的 url 很短只有幾百,而且從調(diào)用的堆棧上來(lái)看是 FormUrlEncodedContent 的 bug,然后根據(jù)異常堆棧信息去看了一下源碼,部分源碼如下:

首先看 FormUrlEncodedContent 做了什么:

然后再找上一層堆棧信息,Uri是一個(gè)分部類(partial),你如果直接在 Github 上 Find 的話會(huì)找到多個(gè) Uri 相關(guān)的文件,最后在 UriExt 中找到了上面的 EscapeDataString 方法:

最后來(lái)看最上層的堆棧信息 UriHelper.EsacpeString 方法,找到異常拋出的地方

在 Uri 這個(gè)類中可以找到上面定義的 c_MaxUriBufferSize,它的值是 0xFFF0 轉(zhuǎn)成十進(jìn)制就是 65520

找到問(wèn)題所在之后,就可以避免這個(gè)問(wèn)題了,再遇到這個(gè)問(wèn)題也就知道是怎么回事了,上面的問(wèn)題就是 post 的數(shù)據(jù)太大了,超過(guò)了這個(gè)限制,所以引發(fā)的異常

More

既然知道這個(gè)是 FormUrlEncodedContent 的 bug,那么修復(fù)它就可以通過(guò)避免使用它,可以直接使用 ByteArray Content,或者不需要 Encode 處理直接用 StringContent 也是可以的

后來(lái)在 Github 搜 issue 的時(shí)候發(fā)現(xiàn)也有很多人遇到了這個(gè)問(wèn)題,這個(gè)問(wèn)題會(huì)在 net5 中得到修復(fù),詳見(jiàn) PR https://github.com/dotnet/corefx/pull/41686

文中一些源碼的鏈接在文章最后的 Reference 的部分可以找到

Reference

  • https://github.com/dotnet/corefx/blob/release/3.1/src/System.Net.Http/src/System/Net/Http/FormUrlEncodedContent.cs#L53

  • https://github.com/dotnet/corefx/blob/release/3.1/src/System.Private.Uri/src/System/UriExt.cs#L597

  • https://github.com/dotnet/corefx/blob/release/3.1/src/System.Private.Uri/src/System/UriHelper.cs#L134

  • https://github.com/dotnet/corefx/blob/release/3.1/src/System.Private.Uri/src/System/Uri.cs

  • https://github.com/dotnet/corefx/pull/41686

  • https://github.com/dotnet/corefx/tree/release/3.1

  • https://github.com/WeihanLi/SamplesInPractice/blob/master/HttpClientTest/Program.cs

總結(jié)

以上是生活随笔為你收集整理的小心 HttpClient 中的 FormUrlEncodeContent 的 bug的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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