小心 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IDEA导入MySQL的jdbc驱动出现“java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver”

目录 一、一般的解决思路 1、JDBC下载链接 2、选择下载内容&#xff0c;并进行下载 3、将驱动导入java项目 二、依然导入驱动失败怎么办 当我们在idea中使用java操作mysql数据库时会出现&#xff1a; Exception in thread "main" java.lang.ClassNotFoundExce…

Android程序设计基础-设计布局之伪今日头条主界面

一、 实验目的 &#xff08;1&#xff09; 掌握Andriod Studio的基本使用方法&#xff1b; &#xff08;2&#xff09; 掌握Andriod Studio中常用的控件及其使用方法&#xff1b; 二、实验内容 &#xff08;1&#xff09;使用Android Studio编写任意一个Android程序并运行&a…

基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(一)

系列文章使用 abp cli 搭建项目给项目瘦身&#xff0c;让它跑起来完善与美化&#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API&#xff0c;包装返回模型再说Swagger&#xff0c;分组、描述、小绿锁接入GitHub&#xff0c;用JWT保护你的API异常处理和…

[JavaWeb]Web概念概述

web概念概述 * JavaWeb&#xff1a;* 使用Java语言开发基于互联网的项目* 软件架构&#xff1a;1. C/S: Client/Server 客户端/服务器端* 在用户本地有一个客户端程序&#xff0c;在远程有一个服务器端程序* 如&#xff1a;QQ&#xff0c;迅雷...* 优点&#xff1a;1. 用户体验…

android封装好的Color类中的常量

通过android封装好的Color类中的常量 public static final int BLACK 0xFF000000;public static final int DKGRAY 0xFF444444;public static final int GRAY 0xFF888888;public static final int LTGRAY 0xFFCCCCCC;public static final int WHITE 0xFFFFFFFF;public st…

MySql轻松入门系列——第一站 从源码角度轻松认识mysql整体框架图

一&#xff1a;背景1. 讲故事最近看各大技术社区&#xff0c;不管是知乎&#xff0c;掘金&#xff0c;博客园&#xff0c;csdn基本上看不到有小伙伴分享sqlserver类的文章&#xff0c;看样子这些年sqlserver没落了&#xff0c;已经后继无人了&#xff0c;再写sqlserver是不可能…

[JavaWeb-JDBC]JDBC_快速入门_idea jdbc连接Mysql数据库

快速入门&#xff1a; * 步骤&#xff1a;1. 导入驱动jar包 mysql-connector-java-8.0.17.jar1.复制mysql-connector-java-8.0.17.jar到项目的libs目录下2.右键-->Add As Library2. 注册驱动3. 获取数据库连接对象 Connection4. 定义sql5. 获取执行sql语句的对象 Statement6…

嫌弃俄罗斯的火箭报价太黑!马斯克自己造火箭!SpaceX首次载人发射任务成功!太牛了!...

当你仰望天空&#xff0c;可曾想象到&#xff0c;距地8公里的平流层每分钟有65架飞机在天空穿梭&#xff0c;距地20公里有太阳能激光通信无人机展翅翱翔、高空通信热气球悠闲的漂荡&#xff0c;再往上有世界各大企业的低轨宽带卫星&#xff0c;在往上是各国的若干低轨道、中轨道…

[JavaWeb-HTML]HTML标签_列表标签

列表标签&#xff1a; * 有序列表&#xff1a;* ol:* li:* 无序列表&#xff1a;* ul:* li:

Android studio 实验过程中遇到的问题之android.support.v7.app.AppCompatActivity不能使用的解决办法

android.support.v7.app.AppCompatActivity不能使用的解决办法 在构建项目时使用 android.support.v7.XX android.support.v4.XX发现在xml文件中&#xff0c;原先我最常使用的DrawerLayout变红了。同时在andriod虚拟机上运行时&#xff0c;报错 我不禁陷入了思考。在网络上冲…

ASP.NET Core 3.x API版本控制

前言一般来说需要更改我们API的时候才考虑版本控制&#xff0c;但是我觉得我们不应该等到那时候来实现它&#xff0c;我们应该有一个版本策略从我们应用程序开发时就开始制定好我们的策略&#xff0c;我们一直遵循着这个策略进行开发。我们其实可以通过多种方式进行实现我们API…

[JavaWeb-HTML]HTML标签_文本标签_练习

案列效果: 文本素材: "中关村黑马程序员训练营"是由传智播客联合中关村软件园、CSDN&#xff0c; 并委托传智播客进行教学实施的软件开发高端培训机构&#xff0c;致力于服务各大软件企业&#xff0c;解决当前软件开发技术飞速发展&#xff0c; 而企业招不到优秀人才…

在 WSL2.0 的 Ubuntu 18 里使用 Docker

近日&#xff0c;随着Windows 10 2004版本的发布&#xff0c;WSL 2经过了近一年的insider测试&#xff0c;现在也正式上线了。Windows 10 2004中引入了一个真实的Linux kernel&#xff0c;使得系统全部的系统调用更加兼容。这也是首次&#xff0c;Linux kernel安装在Windows系统…

基本程序单元Activity—Activity生命周期之数据传递小程序

一、 实验目的 &#xff08;1&#xff09; 掌握Andriod Studio的基本使用方法&#xff1b; &#xff08;2&#xff09; 掌握Andriod Studio中常用的控件及其使用方法&#xff1b; 二、 实验内容 题目&#xff1a; 编写一个数据传递的小程序&#xff0c;要求在第一个界面输入…

[JavaWeb-HTML]HTML标签_图片标签

图片标签&#xff1a; * img&#xff1a;展示图片* 属性&#xff1a;* src&#xff1a;指定图片的位置* 代码&#xff1a;<!--展示一张图片 img--><img src"image/jingxuan_2.jpg" align"right" alt"古镇" width"500" height…

Asp.Net Core+Dapper开发直播平台!

现在直播大热&#xff0c;从游戏直播到直播带货&#xff0c;这几年都是最热门的了。教育直播、视频会议、云点播等各种基于直播构建的业务模式&#xff0c;让众多企业也都开始配备自己的直播平台。14年在公司带队做了个游戏直播平台&#xff0c;疫情期间在家重构了下项目&#…

2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)C题 图墙+拉格朗日四平方数和定理

题意&#xff1a; 其实就是问一个数字能不能表示成5个正平方数的和. 题目&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/problem/220347 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#x…

Magicodes.IE 在100万数据量下导入导出性能测试

原文作者&#xff1a;HueiFeng前言目前Magicodes.IE更新到了2.2.3&#xff0c;感谢大家的支持&#xff0c;同时建议大家在使用过程中如果遇到一些问题或者说需要一些额外的功能可以直接提issues&#xff0c;当然更建议大家提PR。‍近期更新2020.05.24 【Nuget】版本更新到2.2.2…

2018 蓝桥杯省赛 A 组模拟赛(一)数列求值+推导

题目&#xff1a; 对于一个含有 n2个元素的数列&#xff0c;A0、A1、……、An1A_{0}、A_{1}、……、A_{n1}A0​、A1​、……、An1​ &#xff0c;满足这样的递归公式 AiAi−1Ai12−CiA_{i}\frac{A_{i-1}A_{i1}}{2}-C_{i}Ai​2Ai−1​Ai1​​−Ci​ 现在我们知道 A0、An1A_{0}、…