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

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

[[344474]]

本文转载自微信公众号「Dotnet Plus」,作者小码甲 。转载本文请联系Dotnet Plus公众号。   

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

  1. POST   /open-api/v1/user-info?client_id&timstamp&rd=12345&sign=***&method=hmac 
  2. content-type: application/json 
  3. payload: { "token":"AA2917B0-C23D-40AB-A43A-4C4B61CC7C74"

 

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

1. 入坑

下面是构造HttpClient对象、发起请求的代码:

  1. // 初始化HttpClientFactory 
  2. context.Services.AddHttpClient("platform", c => 
  3.     c.BaseAddress = new Uri("https://alpha-engage.demohost.com/"); 
  4.     c.DefaultRequestHeaders.Accept 
  5.     .Add(new MediaTypeWithQualityHeaderValue("application/json")); 
  6. })... 
  7.  
  8. // 产生命名HttpClient,发起请求 
  9.  var client = _clientFactory.CreateClient("platform"); 
  10.  var response = await client.PostAsync($"open-api/v1/user-token/info?{req.AuthString()}",new StringContent(req.ReqPayload.ToString(),Encoding.UTF8) ); 

平台日志显示,收到的请求payload:

  1. {\"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时(下面黄色背景行代码):

  1. context.Services.AddHttpClient("platform", c => 
  2.     c.BaseAddress = new Uri("https://alpha-engage.demohost.com/"); 
  3.     c.DefaultRequestHeaders.Accept 
  4.          .Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header 
  5.     c.DefaultRequestHeaders.Add("content-type""application/json"); 
  6. }) 

此时抛出以下异常:

  1. InvalidOperationException: Misused header name. Make sure request headers are used with 
  2. HttpRequestMessage, response headers with HttpResponseMessage, and 
  3. content headers with HttpContent objects.  

纳尼,HttpContent Headers是啥?Chrome dev tools显示只有两种Header啊?

 

2. 爬坑

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

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

虽然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

  1.  using (var request = new HttpRequestMessage()) 
  2.      request.Method = new HttpMethod(method); 
  3.      request.RequestUri = new Uri(url); 
  4.      request.Content = new StringContent(payload); 
  5.      request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 
  6.      var response = await _httpClient.SendAsync(request); 
  7.      return response; 

使用HttpClient.SendAsync(request)

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

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

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

 

责任编辑:武晓燕 来源: Dotnet Plus
相关推荐

2022-11-18 07:34:12

Docker项目目录

2021-09-09 18:12:22

内存分段式网络

2024-04-10 08:39:56

BigDecimal浮点数二进制

2023-03-06 07:50:19

内存回收Go

2020-09-06 10:02:32

项目管理战略目标CIO

2020-03-31 16:02:23

戴尔

2022-11-27 17:21:04

ClickHouseJDBC函数

2020-04-14 10:06:20

微服务Netflix语言

2019-10-30 14:44:41

Prometheus开源监控系统

2021-07-28 05:01:29

Lombok前端测试

2023-05-15 20:11:34

2020-09-15 08:46:26

Kubernetes探针服务端

2022-12-07 15:37:32

参数不定参数

2020-12-22 09:34:20

JavaScript开发技术

2023-01-18 23:20:25

编程开发

2020-10-22 09:09:41

Python数据科学代码

2021-10-28 19:10:02

Go语言编码

2017-05-05 08:12:51

Spark共享变量

2021-07-26 06:57:58

系统CSS Content

2021-04-14 17:34:18

线程安全
点赞
收藏

51CTO技术栈公众号