日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

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

發布時間:2023/12/13 综合教程 28 生活家
生活随笔 收集整理的這篇文章主要介紹了 我又踩坑了!如何为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、Connection 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

總結

以上是生活随笔為你收集整理的我又踩坑了!如何为HttpClient请求设置Content-Type?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。