為什么HTTP請求行中會出現“https”?


問題

HTTP明明是跑在TLS之上,怎么會意識到https的存在呢?


太長不看

在HTTP/1.1給正向代理的請求行中,方法后面的參數是 absoluteURI ,而非 http URL,即可以使用任何代理支持的協議。 也就是說,該參數表達的是任何可以識別特定資源的標志,所以https作為一種協議可能會出現在該位置。


文檔規定

RFC2616 中,規定請求行的格式為 Method SP **Request-URI** SP HTTP-Version CRLF ,而 Request-URI 的格式為 "*" | absoluteURI | abs_path | authority 。其中,abs_path 是我們最常看到的,例如 /pub/WWW/TheProject.html,通過聯合請求頭中的HOST字段,我們就可以訪問到資源了。


但有時我們的HTTP請求是給一個正向代理的。HTTP/1.1規定,在這種情況下,Request-URI 必須 absoluteURI 的格式,即 scheme ":" ( hier_part | opaque_part ) 。其中,scheme 定義了該URI的命名空間,告訴了代理該資源標識符的語義和語法。所以,它可以是 https:// … 或者 ftp:// … ,甚至可以不指定協議,例如 file:// …


同時,為了避免在代理的過程中產生回環, RFC2616 要求代理的實現必須能夠通過 absoluteURI 確定資源所有的服務器/別名,IP地址,主機名等。


設計分析

為什么給正向代理的HTTP請求行中需要URI,而非 abs_path + HOST字段?

因為這里只確定客戶端和代理之間是通過HTTP協議通信的,並不知道代理會通過何種方式訪問資源。所以我們需要在HTTP請求行中告知代理URI,如果代理支持對應的訪問,則在成功獲取資源后通過HTTP返回給客戶端。

另外,除了直接請求資源服務器,代理也可能把這個請求交給下一個代理,這之間的通信也可能不是基於HTTP的,只有代理在知道完整URI的情況下才能確保接下來的步驟正確運行。


如果使用絕對URI,是否會和HOST字段的信息產生冗余?

在HTTP/1.1中,HOST字段是強制的。其目的是告知服務端請求資源所在的(虛擬)主機和端口號,例如 Host: www.w3.org 所以代理請求行中的絕對URI是會和HOST產生信息冗余的。事實上,RFC7230 規定這種情況下代理必須忽略HOST字段信息,並通過請求行中的URI重新填充HOST字段。


為什么實現不良的代理可能會產生回環?

在現在的網絡環境下,CDN/反向代理的情況非常普遍。CDN的邊際網絡會根據請求選擇直接返回緩存或者繼續轉發請求,所以一個請求可能會被多次代理。但是,如果代理無法、或錯誤的判斷資源來源時,就可能發生回環。例如,代理 A 判斷應該把請求交給代理B,但是 B 在接到請求后認為該請求應該交給代理 A ,這樣就形成了回環(也可能有多個節點),最終導致請求被丟棄。

如上圖所示,這種回環的發生不僅導致了數據的丟失,也耗費了大量帶寬和代理的資源。事實上,這也被作為一種對CDN的“杠桿”拒絕服務攻擊


關於如何通過擴展HTTP頭來解決這個問題,可以參考 Preventing Request Loops Using CDN-Loop


后記

回到最初的問題,如上所述,代理對於不同 scheme 的支持完全取決於實現,如果代理無法支持以 https:// 開頭的代理請求,則會返回4xx狀態。例如 CDN 提供商 fastly 在4年前就是這樣



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM