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") );

干货旁白

  1. 小编对于Http协议有知识漏洞,搬砖时一直关注Chrome DevTools,忽略了还有Entity Header一说。
  2. Content-Type 这个实体标头,会出现了请求/响应标头,指示资源的媒体类型。
  3. .NTE针对4种HTTP Header强化了区别,在实际开发中要灵活使用。

我又踩坑了!如何为HttpClient请求设置Content-Type?的更多相关文章

  1. Flask框架踩坑之ajax跨域请求

    业务场景: 前后端分离需要对接数据接口. 接口测试是在postman做的,今天才开始和前端对接,由于这是我第一次做后端接口开发(第一次嘛,问题比较多)所以在此记录分享我的踩坑之旅,以便能更好的理解,应 ...

  2. Selenium爬虫实践(踩坑记录)之ajax请求抓包、浏览器退出

    上一篇: 使用Selenium截取网页上的图片 前言 最近在搞公司内部系统,累的一批,需要从另一个内部系统导出数据存到数据库做分析,有大量的数据采集工作,又没办法去直接拿到那个系统的接口,太难了,只能 ...

  3. 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 ...

  4. HttpWebRequest 改为 HttpClient 踩坑记-请求头设置

    HttpWebRequest 改为 HttpClient 踩坑记-请求头设置 Intro 这两天改了一个项目,原来的项目是.net framework 项目,里面处理 HTTP 请求使用的是 WebR ...

  5. WebForm路由踩坑 ajax请求多次

    WebForm路由踩坑 再次接触Asp.Net WebForm已是4年后的今天,源起新入职的公司,一个老的项目. Web接触的少,那就多动手写写. WebForm1.aspx <body> ...

  6. HttpClient在多线程环境下踩坑总结

    问题现场 在多线程环境下使用HttpClient组件对某个HTTP服务发起请求,运行一段时间之后发现客户端主机CPU利用率呈现出下降趋势,而不是一个稳定的状态. 而且,从程序日志中判断有线程处于han ...

  7. 微信小程序 请求签名接口超时 踩坑路。。

    我们公司一般做开发都是先用测试机的接口调试功能,等功能都调试的差不多了,再换成线上的正式接口,因为正式接口要验证签名. 这几个功能都调试的差不多了,准备换成线上正式接口了,结果却出了问题,提示请求超时 ...

  8. 【踩坑记】从HybridApp到ReactNative

    前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...

  9. html2canvas以及domtoimage的使用踩坑总结

    前言 首先做个自我介绍,我是成都某企业的一名刚刚入行约一年的前端,在之前的开发过程中,遇到了问题,也解决了问题,但是在下一次解决相同问题的时候,只对这个问题有一丝丝的印象,还需要从新去查找,于是,我注 ...

  10. 我的微信小程序入门踩坑之旅

    前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...

随机推荐

  1. [转帖]各个版本Windows系统中自带的.NET Framework版本

    ① Windows Server : Windows Server版本 自带的.NET Framework 版本 Windows Server 2022 .NET Framework 4.8 Wind ...

  2. [转帖]阿里云Redis开发规范(供大家参考)

    一.键值设计 1. key名设计 (1)[建议]: 可读性和可管理性 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id ugc:video:1 (2)[建议]:简洁性 ...

  3. [转帖]Linux终端:用cat命令查看不可见字符

    https://developer.aliyun.com/article/80607 printf 'testing\012\011\011testing\014\010\012more testin ...

  4. [转帖]JMeter InfluxDB v2.0 listener plugin

    https://github.com/mderevyankoaqa/jmeter-influxdb2-listener-plugin Support my Ukrainian Family ️ Lik ...

  5. [转帖]wmic命令介绍

    https://www.jianshu.com/p/3e1a5a8fa23b How to Get Your System Serial Number PS C:\windows\system32&g ...

  6. buildkit ctr 与 k3s的简单学习

    摘要 前面一部分学习了 buildkit的简单搭建 也学习会了如果build images的简单处理 但是搭建镜像只是万里长征第一步. 如何进行微服务部署,才是关键的第二步. 公司最近使用基于K3S的 ...

  7. 阿里云ECS虚拟机磁盘扩容过程

    阿里云ECS虚拟机磁盘扩容过程 背景 公司同事将很早之前的一个虚拟机重新开机. 就好将一套demo环境安装进这个ECS虚拟机里面 这个机器系统盘只有40G的空间. 导致磁盘空间不足. 其实一开始我不知 ...

  8. .Net Core 3.1浏览器后端服务(二) Web API项目分层

    一.前言 分层开发的思想在计算机领域中至关重要,从操作系统到软件设计,分层思想无处不在. 在搭建项目的分层结构前,先简单了解下分层的优缺点.如下图,分为(呈现层.业务层.服务层.数据层) 分层的优点: ...

  9. 【JS 逆向百例】猿人学系列 web 比赛第二题:js 混淆 - 动态 cookie,详细剖析

    逆向目标 猿人学 - 反混淆刷题平台 Web 第二题:js 混淆,动态 cookie 目标:提取全部 5 页发布日热度的值,计算所有值的加和 主页:https://match.yuanrenxue.c ...

  10. .net fromwork连接rabbitmq发布消息

    1.创建连接工厂类 var factory = new RabbitMQ.Client.ConnectionFactory() { HostName = "120.237.72.46&quo ...