之前兩次singnalr、 websocket實時推播相關:
tag: 瀏覽器--->nginx--> server
其中提到nginx預設不會為使用者端轉發Upgrade
、Connection
檔頭, 因為為了讓被代理的後端伺服器知道使用者端要升級協定,故要在nginx上顯式轉發檔頭:
location /realtime/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
事情本該就就這麼簡單, 但devops總會有各種奇怪的姿勢。
但是運維在給nginx設定的時候,給/
根路徑設定了webcoket協定升級檔頭。
按照字面理解,導致所有的使用者端轉發請求都在要求切換到websocket協定,但是除了/chat路徑, 伺服器其他http路徑並沒有做websocket協定的邏輯,其他http請求是不是都該報錯了。
是實際看,所有的請求(websocket、http)都沒有報錯,都按照指定預期返回。
利用asp.netcore預設腳手架專案:
已知http://localhost:5000/WeatherForecast
是http請求,返回一大坨json資料;
在WeatherForecast
新增斷言紀錄檔:
模擬ops的錯配效果,我們給這個請求新增websocket協定升級檔頭。
第一次:curl 'http://localhost:5000/WeatherForecast' -H 'Upgrade: websocket' -H 'Connection: Upgrade' --verbose
,正常返回大坨json資料。
紀錄檔記錄:
該請求是不是webcocket請求:False,headers:[Accept, */*], [Connection, Upgrade], [Host, localhost:5000], [User-Agent, curl/7.79.1], [Upgrade, websocket]
以上說明,伺服器端並不認為是websocket請求, 這也印證了ops雖然錯配,但對於常規的http請求沒造成影響。
依次判斷;
這樣我們就明白了,雖然websocket協定基於http,新增了httpConnection
、Upgrade
檔頭,但是瀏覽器實際會給我們帶上Sec-WebSocket-Key
、Sec-WebSocket-Version
檔頭,以向伺服器證明這是一個有效的websocket握手。
於是我們可以使用
curl 'http://localhost:5000/WeatherForecast' -H 'Upgrade: websocket' -H 'Connection: Upgrade' -H 'Sec-WebSocket-Version: 13' -H 'Sec-webSocket-Key: eeZn6lg/rOu8QbKwltqHDA==' --verbose
仿造使用者端websocket請求。
紀錄檔記錄:
該請求是不是webcocket請求:True,headers:[Accept, */*], [Connection, Upgrade], [Host, localhost:5000], [User-Agent, curl/7.79.1], [Upgrade, websocket], [Sec-WebSocket-Version, 13], [Sec-WebSocket-Key, eeZn6lg/rOu8QbKwltqHDA==]
對於這個websocket請求,伺服器端還是按照http程式碼邏輯返回200ok和JSON資料,從這個層面上看,http協定是相容websocket的。
真正要讓伺服器端按照websocket姿勢, 要使用HttpContext.WebSockets.AcceptWebSocketAsync()
告知使用者端開始切換協定,並在原tcp上發起全雙工通訊。
前後對比, 困惑得解: 雖然nginx為http請求轉發了Connection
、Upgrade
檔頭, 但是伺服器並不認可這是websocket升級協定,認為是攜帶了特殊檔頭的http請求,走原來的http業務處理邏輯是沒有問題的。
本文來自部落格園,作者:{有態度的馬甲},轉載請註明原文連結:https://www.cnblogs.com/JulianHuang/p/16558322.html
歡迎關注我的原創技術、職場公眾號, 加好友談天說地,一起進化