HTTP協議之Expect爬坑

前言

今天,在對接一個第三方平臺開放接口時遇到一個很棘手的問題,根據接口文檔組裝好報文,使用HttpClient發起POST請求時一直超時,對方服務器一直不給任何響應。

發起請求的代碼如下:

using?(var?httpClient?=?new?HttpClient())
{var?msg?=?new?HttpRequestMessage(){Content?=?new?StringContent(postJson,?Encoding.UTF8,?"application/json"),Method?=?HttpMethod.Post,RequestUri?=?new?Uri(apiUrl),};//?這里會一直阻塞,直到超時var?res?=??httpClient.SendAsync(msg).ConfigureAwait(false).GetAwaiter().GetResult();if?(res.StatusCode?!=?HttpStatusCode.OK){throw?new?Exception(res.StatusCode.ToString());}return?res.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
}

異步請求超時取消錯誤如下:b41ae98fb219ecda9832c8386f4bda8b.png這種情況首先懷疑對方服務是不是有問題 然而經過確認,對方服務沒問題,并且使用將請求的url報文粘貼到PostMan進行請求,迅速得到返回報文,一切正常。

排除了對方服務的問題,那是我們的代碼問題?可是上面HttpClient發起Post請求的代碼寫了不知道多少遍,一直都沒問題,今天怎么就不行了呢,我敢保證這么寫沒毛病。

遇到這種情況該如何解決呢?

爬坑過程

遇到這種問題,相比大部分人開始各種參數換來換去,各種庫換來換去,可能最終蒙成了。但是這里我相信PostMan可以請求成功,強大的HttpClient一定可以,一定是是哪個參數問題,有經驗的老手首先就會想到: 接口的協議中是不是對Header有什么特別的要求,這里查詢文檔,沒有什么特別要求。

控制變量法

既然我們不知道為什么,也猜不到,那就控制變量法去解決。這里能想到的就是抓包,抓取PostMan成功的請求報文以及我們失敗的報文,對比差異。

抓包工具使用的是Fiddler

Postman報文

POST?http://xxx.xxx.xxx.xxx:30000/parking/carin/V1?HTTP/1.1
Content-Type:?application/json
User-Agent:?PostmanRuntime/7.29.2
Accept:?*/*
Postman-Token:?14547b64-d8f6-4b0b-9fa9-48c9ec74a8f6
Host:?xxx.xxx.xxx.xxx:30000
Accept-Encoding:?gzip,?deflate,?br
Connection:?keep-alive
Content-Length:?563{"data":?...這里省略了具體json內容}

HttpClient報文

POST?http://118.31.110.35:30000/parking/carin/V1?HTTP/1.1
Content-Type:?application/json;?charset=utf-8
Host:?118.31.110.35:30000
Content-Length:?563
Expect:?100-continue
Connection:?Keep-Alive{"data":?...這里省略了具體json內容}

差異排查

  1. 因為body中的內容是一樣的,這里就不用對比了。

  2. 兩個請求的Header存在差異,那我們就將差異一個一個抹平。

  3. Content-TypeHttpClient中多了charset=utf-8,這個應該不影響,http協議默認就是utf8。

  4. User-AgentHttpClient中沒有,那我們加上一模一樣的User-Agent,測試,依舊超時。

  5. AcceptHttpClient中沒有,抹平,測試,依舊超時。

  6. Postman-TokenHttpClient中沒有,抹平,測試,依舊超時。

  7. Accept-EncodingHttpClient中沒有,抹平,測試,依舊超時。

到這里Postman中有的,我們HttpClient中都有了,竟然還超時,這里雖然已經保證大部分參數都一樣了,但是控制變量法要求所有參數都一樣,這里還沒有保證,因為HttpClient多了一個Expect頭,我們還沒保證一致。

  1. HttpClient的請求頭中Expect: 100-continuePostman報文中不存在,去掉Expect,測試,成功了!!

  2. 那我們鎖定Expect: 100-continue導致了我們的請求無響應,還原之前所有的抹平操作,僅僅移除Expect: 100-continue,測試,依然成功。

本文為Gui.H原創文章,發布于公眾號:dotnet之美

博客園首發:https://www.cnblogs.com/springhgui/p/16499439.html

最終解決前言中的問題,僅僅需要添加一行代碼

msg.Headers.ExpectContinue?=?false;

ExpectContinues屬性文檔:ce550900d3b45b45b96dbe0307568638.png

至此問題解決,控制變量yyds

Expect是什么

參考Expect的定義 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect

Expect?是一個請求消息頭,包含一個期望條件,表示服務器只有在滿足此期望條件的情況下才能妥善地處理請求。

Expect

規范中只規定了一個期望條件,即?Expect: 100-continue, 對此服務器可以做出如下回應:

  • 100?如果消息頭中的期望條件可以得到滿足,使得請求可以順利進行的話,

  • 417?(Expectation Failed) 如果服務器不能滿足期望條件的話;也可以是其他任意表示客戶端錯誤的狀態碼(4xx)。

例如,如果請求中?Content-Length?的值太大的話,可能會遭到服務器的拒絕。

Expect有啥好處

讓客戶端在發送請求數據之前去判斷服務器是否愿意接收該數據,如果服務器愿意接收,客戶端才會真正發送數據,如果客戶端直接發送請求數據,但是服務器又將該請求拒絕的話,這種行為將帶來很大的資源開銷。

Expect有啥坑

不是所有的服務器都會正確應答100-continue, 比如lighttpd, 就會返回417 Expectation Failed。

超時的原因

HttpClient默認攜帶了Expect頭,我們請求帶上了Expect: 100-continue的話是不會立刻發送body中的報文給服務器,需要服務器需要對Expect: 100-continue做出響應,然而對方服務器不支持Expect當然不能做出響應,在前言說的問題中,也就是HttpClient在等對方服務器響應Expect,然后再發送報文,而對方服務器看來,我們怎么還不發送報文過來,雙方都在等數據,最終HttpClient超時~

以上純屬個人理解,有不正確之處,還請指正~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284555.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284555.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284555.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【ArcGIS微課1000例】0028:ArcGIS根據屬性快速分割生成多個shp文件

ArcGIS10.5及以上的版本提供了按屬性分割工具,(分析工具->提取->按屬性分割)工具。也可以使用10.2版本的分割工具,效果應該是一樣的。本文演示使用分割工具批量快速提取一個縣范圍內的多個鎮,生成多個鎮矢量shp數據。 擴展閱讀:【ArcGIS遇上Python】ArcGIS Python按…

Win11 恢復 Win10經典右鍵菜單 親測有效

管理員運行命令: reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve 重…

把一個字符串里符合表情文字標簽的地方全部替換為相應的圖片的方法

1、表情數據: var emotion [{"name": "Expression_1","text": "[微笑]"},{"name": "Expression_2","text": "[撇嘴]"},{"name": "Expression_3","text&…

【ArcGIS微課1000例】0029:ArcGIS繪制平行線(構造平行公路)

在實際工作中,有時需要繪制平行線,比如道路兩邊的邊界線,可以使用“平行復制”功能快速繪制平行線,本文介紹如何使用“平行復制”功能快速繪制平行線。 1. 加載公路矢量 加載配套實驗數據包中的數據0029.rar中的矢量數據:公路。 2. 生成平行公路 點擊“編輯器”→“開始…

2017年初隨想——幾個小目標

回顧往事很慘,展望未來渺茫 2016年不順的事情一籮筐,母親追求信仰(誤入歧途)導致父母離婚,父親又遭遇車禍,現在依然癱瘓在床,意識都尚未清醒,母親卻依然杳無音信。而我則剛工作2年半…

Win11 沒有磁盤清理工具,如何清理磁盤舊的windows.old文件

win11 磁盤右鍵沒有了“磁盤清理工具” 如果想清理文件,可以打開設置(WinI)系統—存儲—清理建議 您也可以打開“存儲感知”,系統會在需要時幫你自動清理文件。

腳本進階,函數調用實例練習

一、練習:腳本:判定192.168.0.200-192.168.0.254之間哪些主機在線,要求:1、使用函數來實現一臺主機的判定過程:2、在主程序中調用此函數判定指定范圍內的所有主機的在線情況,vim ping.sh#!/bin/bash#PING()…

.NET開發云原生應用,你只差給自己加個油

為什么要云原生(Cloud Native)Cloud表示應用程序位于云中,而不是傳統的數據中心;Native表示應用程序從設計之初即考慮到云的環境,原生為云而設計,在云上以最佳姿勢運行,充分利用和發揮云平臺的彈…

java成員變量的初始化

2019獨角獸企業重金招聘Python工程師標準>>> 類變量(static變量,不需要實例化對象也可以引用) 實例變量(非static變量,需要實例化對象) 局部變量(類的成員函數中的變量) 初始化方式: 構造函數初始化 變量聲明時初始化 代碼塊初始化 java自動初始化(在構造函數執行之…

Win11 的日歷 替代

Win11 的日歷雖然漂亮,卻少了很多小功能,特別是沒有秒鐘和日程的設計,讓用慣了 Win10 的小伙伴大呼不滿。原來曾經用過360帶的日歷,可惜不支持Win11,下面這個日歷是一款功能強大、顏值很高的小工具,能夠提供…

ReactNative--React簡介

React 基礎框架,是一些實現理念,不能用來做網頁的開發和手機應用的開發 React.js 用來做網頁開發 ReactNative 移動應用開發 在學習ReactNative之前,先學習React http://reactnative.cn/ 中文網 http://facebook.github.io/react-nativ…

【ArcGIS微課1000例】0030:ArcGIS利用MXD doctor工具分析并修復mxd地圖文檔

MXD Doctor 是一個獨立的應用程序,位于 ArcGIS Desktop 安裝目錄下的 Tools 文件夾中。該工具可用于分析已損壞的 .mxd 文件。根據分析結果,可將已損壞的 .mxd 文件中所包含的實體復制到新的或現有 .mxd 文件中。 可以從所有程序 > ArcGIS > Desktop 工具中打開 MXD Do…

分析一個 .NET 寫的 某 RFID標簽系統 CPU暴漲

一:背景 1. 講故事前段時間有位朋友說他的程序 CPU 出現了暴漲現象,由于程序是買來的,所以問題就比較棘手了,那既然找到我,就想辦法幫朋友找出來吧,分析下來,問題比較經典,有必要和大…

linux開機引導過程總覽

簡單的說,系統的啟動過程如下: 1.開機自檢: 按下電源按鍵后,計算機硬件會主動讀取BIOS加載硬件信息并進行硬件的自我測試,然后系統會根據BIOS里的啟動順序讀取第一個可啟動的設備,從而移交系統控制權&#…

CentOS關機與重啟命令詳解

2019獨角獸企業重金招聘Python工程師標準>>> Linux centos重啟命令: 1、reboot  2、shutdown -r now 立刻重啟(root用戶使用)  3、shutdown -r 10 過10分鐘自動重啟(root用戶使用)  4、shutdown -r 20:35 在時間為20:35時候重啟(root用戶使用)如果…

JS正則提取字符串

河北科技師范學院歐美學院新聞標題 河南大學邁阿密學院新聞標題 首都經濟貿易大學密云分校新聞標題 北京科技大學(延慶校區)新聞標題 湖北中醫藥大學職業技術學院新聞標題 公安消防部隊高等專科學校新聞標題 從上邊的類似新聞標題中提取完整學校名稱,最終參考代…

【工具】PC端調試手機端 Html 頁面的工具

一、概述 有一個項目需要在手機端顯示一個 web 頁面,而每次把應用 launch 后,從手機端看比較麻煩,因此搜羅了幾種在 PC 端調試手機端頁面的工具。 二、工具 http://fonkie.iteye.com/blog/1846858 http://blog.csdn.net/dojotoolkit/article/…

【ArcGIS微課1000例】0031:ArcGIS中的32個拓撲規則(圖文詳解)

在地理數據庫中,拓撲是定義點要素、線要素以及面要素共享重疊幾何的方式的排列布置。例如,街道中心線與人口普查區塊共享公共幾何,相鄰的土壤面共享公共邊界。學習拓撲就必須掌握ArcGIS中常見的拓撲規則。 文章目錄 一、面的拓撲規則(10種)二、點的拓撲規則(6種)三、線的…

Blazor University (38)JavaScript 互操作 —— 從 .NET 調用 JavaScript

原文鏈接:https://blazor-university.com/javascript-interop/calling-javascript-from-dotnet/從 .NET 調用 JavaScriptJavaScript 應添加到服務器端 Blazor 應用程序的 /Pages/_Host.cshtml 或 Web Assembly Blazor 應用程序的 wwwroot/index.html 中。然后可以通…

十大排序總結(js實現、穩定性、內外部排序區別、時間空間復雜度、冒泡、快速、直接選擇、堆、直接插入、希爾、桶、基數、歸并、計數排序)

目錄 排序相關概念 穩定性 內部排序 外部排序 十種排序算法特點總結 交換排序 冒泡排序(數組sort方法的原理) 圖解 js實現 特點 快速排序 圖解 js實現 特點 選擇排序 直接選擇排序 圖解 js實現 特點 堆排序 大(小&#xff0…