我又踩坑了!如何为HttpClient请求设置Content-Type标头?

简介: 小编对于Http协议有知识漏洞,搬砖时一直关注Chrome DevTools,忽略了还有Entity Header一说

近在重构认证代码,认证过程相当常规:


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"}


a0767877c181c6598cd1ffe9a3bda1bf.png


平台显示 :签名校验失败, 排查到平台收到的Post Payload并非预期,阅读本文,解锁正确使用Content-Type标头的姿势。


1. 入坑


下面是构造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接收端没有识别出JSON 格式的payload , 进行了转码,生成了错误签名。


① Content-Type是一个Entity Header,指示资源的mediaType ,可用在请求/响应中

② 代码中new StringContent(req.ReqPayload.ToString(),Encoding.UTF8) 没有指定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啊?


46173861309e4a89a9c798ce1aa1d1c5.png


2.  爬坑


官方资料显示:HTTP Headers被分为如下四类:


--- 信息 举例
.NET类型
General Header 可同时作用在请求/响应中,但是与传输数据无关 Upgrade、Connection ---
Request Header 将要获取的资源或客户端本身的信息 Accept、
Authorization
HttpRequestHeaders
Response Header 响应信息 Location、ETag HttpResponseHeaders
Entity
Header
实体Body额外的信息 Content-Length、
Content-Type
HttpContentHeaders


Content-Type属于Entity Header的一种,对应.NET类型  HttpContentHeader;


虽然Entity Header不是请求标头也不是响应标头,它们还是会包含在请求/响应标头术语中(此说法来自官方)。


所以我们在Chrome DevTools没有看到Entity Headers分组, 却常在请求/响应标头中看到Content-Type标头。


回到上面的异常,.NET 严格区分四种标头,所以c.DefaultRequestHeaders.Add("content-type", "application/json") 尝试将content-type添加到请求头,姿势不正确,.NET提示InvalidOperationException


3. 填坑


给这个常规的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)


方法② 写入HttpContent时传入媒体类型


StringContent某个重载构造函数 : 参数3 可直接设置media type


var response = await client.PostAsync($"open-api/v1/user-token/info?{req.AuthString()}",new StringContent(req.ReqPayload.ToString(),Encoding.UTF8,"application/json") );


4.干货旁白


  1. 小编对于Http协议有知识漏洞,搬砖时一直关注Chrome DevTools,忽略了还有Entity Header一说。


  1. Content-Type 这个实体标头(实体标头通常会出现在请求/响应标头中),指示资源的媒体类型。


  1. .NTE针对4种HTTP Header强化了区别,在实际开发中要区别使用。
相关文章
|
4月前
|
存储 缓存 API
HTTP 请求的响应头部字段 Cache-Control 的值为 no-store 是什么意思
HTTP 请求的响应头部字段 Cache-Control 的值为 no-store 是什么意思
78 0
|
JSON API 数据格式
Uniapp~动态修改 请求头的content-type 的值
Uniapp~动态修改 请求头的content-type 的值
993 0
Uniapp~动态修改 请求头的content-type 的值
|
数据库
FastAPI(53)- Response Headers 响应设置 Headers
FastAPI(53)- Response Headers 响应设置 Headers
467 0
FastAPI(53)- Response Headers 响应设置 Headers
|
前端开发 Java
Java 技术篇 - 前端浏览器发送一次url请求后端ServerSocket接收到两次请求原因及解决方法,GET /favicon.ico HTTP/1.1问题处理
Java 技术篇 - 前端浏览器发送一次url请求后端ServerSocket接收到两次请求原因及解决方法,GET /favicon.ico HTTP/1.1问题处理
660 0
Java 技术篇 - 前端浏览器发送一次url请求后端ServerSocket接收到两次请求原因及解决方法,GET /favicon.ico HTTP/1.1问题处理
|
4月前
|
XML JSON 编解码
HTTP Content-Type 类型解析
【1月更文挑战第10天】HTTP Content-Type 类型解析
|
7月前
|
Web App开发 JSON 数据格式
使用 http-proxy 代理 HTTP 请求时遇到的 the requested url is invalid 错误消息
使用 http-proxy 代理 HTTP 请求时遇到的 the requested url is invalid 错误消息
112 0
|
8月前
|
前端开发 Java
java在过滤器中为http请求加请求头header
现在有一个需求场景是,每一个请求我都需要在请求头里面加上token这个请求头,作为一种校验机制,传统的接口可以通过设置一个全局的变量,然后通过页面携带过来(大概就是先将我们的token放在session中,写一个服务用来获取session中的token,然后主页面用ajax调用接口,将token放在隐藏域中,然后将请求头放进来,用ajax方法,这里不想洗说了),但是有一种情况是通过页面传递的并不一定都会适用所有接口,比如上传和下载的接口有时候头里面就没有token参数,可能是上传和下载是用表单提交的 这个时候如何将请求头通过后台的方法加进来? 想到用过滤器,用后台方法强制加入请求头。
98 0
|
10月前
|
JSON Java 数据格式
Postman发送json数据出现HttpMessageNotReadableException: Required request body is missing的几种解决方法以及页面显示400解决
Postman发送json数据出现HttpMessageNotReadableException: Required request body is missing的几种解决方法以及页面显示400解决
196 0
|
前端开发 JavaScript 应用服务中间件
js/css文件加载失败 HTTP code状态码返回206 Partial Content
js/css文件加载失败 HTTP code状态码返回206 Partial Content
596 0
|
XML JSON 开发工具
浅析http请求的content-type及使用场景
在HTTP协议消息头中,使用Content-Type来表示媒体类型信息。它被用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析html或仅仅展示一个文本等。
267 0