小心 HttpClient 中的 FormUrlEncodeContent 的 bug
小心 HttpClient 中的 FormUrlEncodeContent 的 bug
Intro
最近发现活动室预约项目里的上传图片有时候会有问题,周末找时间测试了一下,发现小图片的上传没问题,大图片上传会有问题,而且异常信息还很奇怪,System.UriFormatException: Invalid URI: The Uri string is too long
看这个错误的信息还以为是请求的 url 过长导致的,但是实际请求的 url 很短,诡异的异常信息
测试示例
为了方便大家了解和测试这个bug,我在 Github 上提供了一个示例 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}");}}}
}
测试代码:
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!");
输出结果如下:
揪出异常始末
上传图片的时候会调用一个码云的一个 POST 接口来保存上传的图片,参数是通过 form-data 的方式传递的,在 POST 的时候报异常了,异常信息很诡异,具体信息和上面的是一样的:
这个异常信息看上去像是 url 过长导致的,但是实际的 url 很短只有几百,而且从调用的堆栈上来看是 FormUrlEncodedContent
的 bug,然后根据异常堆栈信息去看了一下源码,部分源码如下:
首先看 FormUrlEncodedContent
做了什么:
然后再找上一层堆栈信息,Uri
是一个分部类(partial
),你如果直接在 Github 上 Find 的话会找到多个 Uri
相关的文件,最后在 UriExt
中找到了上面的 EscapeDataString
方法:
最后来看最上层的堆栈信息 UriHelper.EsacpeString
方法,找到异常抛出的地方
在 Uri 这个类中可以找到上面定义的 c_MaxUriBufferSize
,它的值是 0xFFF0
转成十进制就是 65520
找到问题所在之后,就可以避免这个问题了,再遇到这个问题也就知道是怎么回事了,上面的问题就是 post 的数据太大了,超过了这个限制,所以引发的异常
More
既然知道这个是 FormUrlEncodedContent
的 bug,那么修复它就可以通过避免使用它,可以直接使用 ByteArray Content,或者不需要 Encode 处理直接用 StringContent 也是可以的
后来在 Github 搜 issue 的时候发现也有很多人遇到了这个问题,这个问题会在 net5 中得到修复,详见 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
小心 HttpClient 中的 FormUrlEncodeContent 的 bug相关推荐
- java string 占位符_驳《阿里「Java开发手册」中的1个bug》?
前两天写了一篇关于<阿里Java开发手册中的 1 个bug>的文章,评论区有点炸锅了,基本分为两派,支持老王的和质疑老王的. 首先来说,无论是那一方,我都真诚的感谢你们.特别是「二师兄」, ...
- (用微信扫的静态链接二维码)微信native支付模式官方提供的demo文件中的几个bug修正...
原文:(用微信扫的静态链接二维码)微信native支付模式官方提供的demo文件中的几个bug修正 native支付模式一demo(用微信扫的静态链接二维码)BUG修复,一共4个BUG 1.nativ ...
- OpenCV中initUndistortRectifyMap函数存在bug原因探究
原文首发于公众号「3D视觉工坊」:OpenCV中initUndistortRectifyMap函数存在bug原因探究. 最近在运行如下一段代码时,生成的mapx和mapy有点异常. 代码片段如下: # ...
- UNITY 中List.Sort的BUG
UNITY 中List.Sort的BUG List<int> lst = new List<int>();lst.Add(202);lst.Add(20);lst.Add(40 ...
- 驳《阿里「Java开发手册」中的1个bug》?
这是我的第 211 期分享 作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 前两天写了一篇关于<阿里Java开发手册中的 1 ...
- go 怎么等待所有的协程完成_理解真实世界中 Go 的并发 BUG
点击上方蓝色"Go语言中文网"关注,回复「电子书」领全套Go资料 有几个学生研究归纳了go编程中的并发bugs,发表了一篇(英文)论文:<Understanding Real ...
- 解决iframe在ios中无法滚动的bug
https://fly.layui.com/jie/32020/(无效) 修改方法: 1.在嵌入进iframe的每个页面的<body>里面加个id,如<body id="i ...
- 5006.c++类中使用static变量bug
c++类中使用static变量bug 正常情况,一般c++类中,不能使用static 定义成员,一般情况下在定义时编译器会进行报错.我呢由于c语言的使用习惯,没有太注意.在c++类的方法中,写代码时顺 ...
- 2021年C++项目中的十大Bug:乍一看都正确的代码,实则暗藏玄机
作者 | Vladislav Stolyarov 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 在程序员的新年祝福中,大家或多或少会来一句,新年编码无Bug.Bug越写越少--对程序员 ...
最新文章
- Vmware Workstation VMX 在资源管理器中杀不掉(虚拟机繁忙导致无法关机)
- 清华特奖答辩前10出炉,两名CS学生3篇顶会一作,有人周读3000页英文论文!
- Linq之延迟加载特性
- 优化器 - tf.keras.optimizers.SGD()【TensorFlow2入门手册】
- Hadoop YARN安装部署初探
- 直接管理内存——new和delete
- Python实现遍历目录与子目录,并找到以.txt结尾的文件
- 搭建samba文件共享服务
- 怎么运行Typescript
- python字频统计软件_python结巴分词以及词频统计实例
- html 长文本 截断 jquery 扩展脚本
- C++ 形参与实参的传递
- 使用samba完成Linux服务器与Windows之间的映射
- java composite 模式_《JAVA设计模式》中的组合模式Composite
- Dxg——C++ 开发笔记整理分类合集【所有的相关记录,都整理在此】
- len函数实例python_Python通过len函数返回对象长度
- MASK RCNN在tensorflow 2.5中运行
- HTML中背景图片如何自适应屏幕
- 当8081端口被占用了怎么办?
- 腾讯市值首破5000亿美元;阿里224亿港币入股高鑫零售;特斯拉新超跑在华接受预定丨价值早报
热门文章
- BZOJ 4516: [Sdoi2016]生成魔咒 [后缀自动机]
- listview嵌套gridview
- linux最常用的20条命令
- shell编程的一些例子4
- chromebook刷机_如何在Chromebook上拍照
- 编写iptables脚本实现IP地址、端口过滤
- 微信支付四大支付模式分别有哪些区别?
- MongoDB基本操作(增删改查)
- nat+端口转发,使得宿主机secureCRT可以访问vbox里linux虚拟机
- linux 学习笔记 显示压缩文件 gong.zip 的文件内容