我又踩坑了!如何为HttpClient请求设置Content-Type?
1. 坑位
最近在重构认证代码,认证过程相当常规:
POST /open-api/v1/user-info?client_id&timstamp&rd=12345&sign=***&method=hmac
content-type: application/json
payload: { "token":"AA2917B0-C23D-40AB-A43A-4C4B61CC7C74"}

平台显示 :签名校验失败, 排查到平台收到的Post Payload并非预期,阅读本文,解锁正确使用Content-Type标头的姿势。
2. 步步为营
下面是构造HttpClient对象、发起请求的代码:
// 初始化HttpClientFactory
context.Services.AddHttpClient("platform", c =>
{
c.BaseAddress = new Uri("https://alpha-engage.demohost.com/");
c.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
})...
// 产生命名HttpClient,发起请求
var client = _clientFactory.CreateClient("platform");
var response = await client.PostAsync($"open-api/v1/user-token/info?{req.AuthString()}",new StringContent(req.ReqPayload.ToString(),Encoding.UTF8) );
平台日志显示,收到的请求payload:
{\"token\":\"AA2917B0-C23D-40AB-A43A-4C4B61CC7C74\"}
额,平台收到的JSON数据被转码了,没有识别出JSON?
明眼人一看,HttpClient请求没有设置Content-Type,接收端没有识别出payload是JSON,接收时进行了转码,生成了错误签名。
① Content-Type是一个Entity Header,指示资源的media type ,可用在请求或者响应中。
② 以上代码中new StringContent(req.ReqPayload.ToString(),Encoding.UTF8)指定了Encoding=UTF-8,却没有指定mediaType,源码默认值:text/plain。
当我尝试添加Content-Type时(下面黄色背景行代码):
context.Services.AddHttpClient("platform", c =>
{
c.BaseAddress = new Uri("https://alpha-engage.demohost.com/");
c.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header
c.DefaultRequestHeaders.Add("content-type", "application/json");
})
此时抛出以下异常:
InvalidOperationException: Misused header name. Make sure request headers are used with
HttpRequestMessage, response headers with HttpResponseMessage, and
content headers with HttpContent objects.
纳尼,HttpContent Headers是啥?Chrome dev tools显示只有两种Header啊?

3. 爬坑
官方资料显示: HTTP Headers被分为如下四类:
| --- | 信息 | 举例 | 对应.NET类型 |
|---|---|---|---|
| General Header | 可同时作用在请求/响应中,但是与传输数据无关 | Upgrade、Connection | --- |
| Request Header | 将要获取的资源或客户端本身的信息 | Accept、Authorization | System.Net.Http.Headers.HttpRequestHeaders |
| Response Header | 响应信息 | Location、ETag | System.Net.Http.Headers.HttpResponseHeaders |
| Entity Header | 实体Body额外的信息 | Content-Length、Content-Type | System.Net.Http.Headers.HttpContentHeaders |
Content-Type属于Entity Header中的一种。
即便Entity Header既不是请求标头也不是响应标头,它们还是会包含在请求/响应标头术语中(此说法来自官方)。
所以我们在Chrome DevTools没有看到Entity Headers分组,却常在请求/响应标头中看到Content-Type标头。
回到上面的异常,.NET 严格区分四种标头,所以我上面
c.DefaultRequestHeaders.Add("content-type", "application/json");尝试在请求头添加Content-Type标头, 姿势错误, .NET会提示InvalidOperationException异常。
4. 填坑
给这个常规的Post请求 设置正确的Content-Type,
① 对HttpRequestMessage对象Content属性添加Header
using (var request = new HttpRequestMessage())
{
request.Method = new HttpMethod(method);
request.RequestUri = new Uri(url);
request.Content = new StringContent(payload);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await _httpClient.SendAsync(request);
return response;
}
使用HttpClient.SendAsync(request)
② 对StringContent重载构造函数传参
StringContent某个重载构造函数可直接传参,设置media type,
var response = await client.PostAsync($"open-api/v1/user-token/info?{req.AuthString()}",new StringContent(req.ReqPayload.ToString(),Encoding.UTF8,"application/json") );
干货旁白
- 小编对于Http协议有知识漏洞,搬砖时一直关注Chrome DevTools,忽略了还有Entity Header一说。
- Content-Type 这个实体标头,会出现了请求/响应标头,指示资源的媒体类型。
- .NTE针对4种HTTP Header强化了区别,在实际开发中要灵活使用。
- https://github.com/microsoft/referencesource/blob/master/System/net/System/Net/Http/StringContent.cs
- https://tools.ietf.org/html/rfc2616#page-42
我又踩坑了!如何为HttpClient请求设置Content-Type?的更多相关文章
- Flask框架踩坑之ajax跨域请求
业务场景: 前后端分离需要对接数据接口. 接口测试是在postman做的,今天才开始和前端对接,由于这是我第一次做后端接口开发(第一次嘛,问题比较多)所以在此记录分享我的踩坑之旅,以便能更好的理解,应 ...
- Selenium爬虫实践(踩坑记录)之ajax请求抓包、浏览器退出
上一篇: 使用Selenium截取网页上的图片 前言 最近在搞公司内部系统,累的一批,需要从另一个内部系统导出数据存到数据库做分析,有大量的数据采集工作,又没办法去直接拿到那个系统的接口,太难了,只能 ...
- C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式
C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...
- HttpWebRequest 改为 HttpClient 踩坑记-请求头设置
HttpWebRequest 改为 HttpClient 踩坑记-请求头设置 Intro 这两天改了一个项目,原来的项目是.net framework 项目,里面处理 HTTP 请求使用的是 WebR ...
- WebForm路由踩坑 ajax请求多次
WebForm路由踩坑 再次接触Asp.Net WebForm已是4年后的今天,源起新入职的公司,一个老的项目. Web接触的少,那就多动手写写. WebForm1.aspx <body> ...
- HttpClient在多线程环境下踩坑总结
问题现场 在多线程环境下使用HttpClient组件对某个HTTP服务发起请求,运行一段时间之后发现客户端主机CPU利用率呈现出下降趋势,而不是一个稳定的状态. 而且,从程序日志中判断有线程处于han ...
- 微信小程序 请求签名接口超时 踩坑路。。
我们公司一般做开发都是先用测试机的接口调试功能,等功能都调试的差不多了,再换成线上的正式接口,因为正式接口要验证签名. 这几个功能都调试的差不多了,准备换成线上正式接口了,结果却出了问题,提示请求超时 ...
- 【踩坑记】从HybridApp到ReactNative
前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...
- html2canvas以及domtoimage的使用踩坑总结
前言 首先做个自我介绍,我是成都某企业的一名刚刚入行约一年的前端,在之前的开发过程中,遇到了问题,也解决了问题,但是在下一次解决相同问题的时候,只对这个问题有一丝丝的印象,还需要从新去查找,于是,我注 ...
- 我的微信小程序入门踩坑之旅
前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...
随机推荐
- [转帖]网站开启 IPv6 的三种方式
https://zhuanlan.zhihu.com/p/443835798 从传统二进制部署的 Nginx ,到云原生部署的 K8S.Istio,分别介绍网站开启 IPv6 的三种方式. 1.Ngi ...
- [转帖]JVM 输出 GC 日志导致 JVM 卡住,我 TM 人傻了
https://www.jianshu.com/p/51380e04eab1 最近,我们升级了 Java 17.后来,我们的 k8s 运维团队为了优化我们的应用日志采集, 将我们所有 pod (你可以 ...
- [转帖]linux将大目录等分切割成多个小目录
https://www.jianshu.com/p/6f9e6743a1dc 需求:有一个目录存放了数十万个文件,现在需要将这个目录上传,如果整个目录上传,中间因为某些故障断开连接了,可能又要从头开始 ...
- minio性能测试
minio性能测试 minio的使用 前期使用了s3fs 但是想验证一下性能相关, 所以使用今天简单验证了一下, 其实也可以使用一下fio 但是s3fs 是对象存储 没有修改 只有上传, 所以感觉还是 ...
- [转帖]MioIO读/写性能测试
https://www.jianshu.com/p/a0a84f91b16f image.png COSBench是Intel团队基于java开发,是一个测试云对象存储系统的分布式基准测试工具,全 ...
- [转帖]【压测】通过Jemeter进行压力测试(超详细)
文章目录 背景 一.前言 二.关于JMeter 三.准备工作 四.创建测试 4.1.创建线程组 4.2.配置元件 4.3.构造HTTP请求 4.4.添加HTTP请求头 4.5.添加断言 4.6.添加察 ...
- [转帖]iptables 执行清除命令 iptables -F 要非常小心的
使用 /sbin/iptables -F 要小心,搞不好,你就马上同服务器断开连接了 以下是来自 http://wiki.ubuntu.org.cn/IptablesHowTo 上的说明 可以通过/s ...
- [转贴]使用dbstart 和dbshut 脚本来自动化启动和关闭数据库
使用dbstart 和dbshut 脚本来自动化启动和关闭数据库 https://www.cnblogs.com/snowers/p/3285281.htmldbshut 和 dbstart 使用db ...
- node借助jsonwebtoken生成token以及验证token是否过期
生成token使用 jsonwebtoken 插件 我当时使用的版本"jsonwebtoken": "^9.0.0", cnpm i jsonwebtoken ...
- 小程序之使用阿里字体图标 定义主题的颜色 控制首页标题的样式 如何使用组件 水平居中和垂直居中的方式 H5 关于上线后,
项目搭建 1==> 需要创建的文件夹 styles 存放公共的样式 components 存放组件 lib第三方库的 utils 自己的帮助库 reques 自己的接口 2==>如何快速创 ...