## 1 下班前的寂靜 剛準備下班呢,測試大姐又給我提個`bug`,你看我這就操作了一次,`network`里咋有兩個請求? 我心一驚,”不可能啊!我代碼明明就調用一次後端介面,咋可能兩個請求!“。打開她的截圖一看:多個`options`請求。 我不慌不忙解釋道:”這不用管,是瀏覽器預設發送的一個預 ...
1 下班前的寂靜
剛準備下班呢,測試大姐又給我提個bug
,你看我這就操作了一次,network
里咋有兩個請求?
我心一驚,”不可能啊!我代碼明明就調用一次後端介面,咋可能兩個請求!“。打開她的截圖一看:多個options
請求。
我不慌不忙解釋道:”這不用管,是瀏覽器預設發送的一個預檢請求“。
可測試大姐好像依舊很執著:“那這可肯定不行啊,明明一次請求,幹嘛要兩次呢,這不是增大服務端壓力嗎?”
“md,真固執啊,那就不下班了,加個鐘給你講懂!”
HTTP請求分為兩種:
- 簡單請求
- 非簡單請求
2 簡單請求
2.1 條件
-
請求方式:
HEAD
、GET
、POST
-
header中只能包含以下請求頭欄位:
-
Accept
-
Accept-Language
-
Content-Language
-
Content-Type所指的媒體類型值僅僅限於下列三者之一
text/plain
multipart/form-data
application/x-www-form-urlencoded
-
2.2 瀏覽器的不同處理方式
簡單請求,若請求跨域,瀏覽器會放行讓請求發出。瀏覽器會發cors
請求,並攜帶origin
。此時不管服務端返回啥,瀏覽器都會把返回攔截,並檢查返回的response
的header
中有無Access-Control-Allow-Origin
:
- 這頭部信息的值通常為請求的
Origin
值,表示允許該來源的請求說明資源是共用的,可以拿到 - 如果
Origin
頭部信息的值為"*"(表示允許來自任何來源的請求)但這種情況下需要謹慎使用,因為它存在安全隱患 - 如沒有這個頭信息,說明服務端沒有開啟資源共用,瀏覽器會認為這次請求失敗終止這次請求,並且報錯。
3 非簡單請求
只要不滿足簡單請求的條件,都是非簡單請求。
發出非簡單cors
請求,瀏覽器會做一個http
的查詢請求(預檢請求)即options
。options
請求會按照簡單請求來處理。
為啥要做一次options
請求?
檢查伺服器是否支持跨域請求,並確認實際請求的安全性。預檢請求是為保護客戶端的安全,防止不受信任網站利用用戶瀏覽器向其他網站發惡意請求。 預檢請求頭中除了攜帶了origin
欄位還包含兩個特殊欄位:
-
Access-Control-Request-Method
: 告知伺服器實際請求使用的HTTP
方法 -
Access-Control-Request-Headers
:告知伺服器實際請求所攜帶的自定義首部欄位
如:
OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
以上報文中就可以看到,使用OPTIONS
請求,瀏覽器根據上面的使用的請求參數來決定是否需要發送,這樣伺服器就可以回應是否可以接受用實際的請求參數來發送請求。
-Access-Control-Request-Method
告知伺服器,實際請求將使用 POST
方法
Access-Control-Request-Headers
告知伺服器,實際請求將攜帶兩個自定義請求標頭欄位:X-PINGOTHER
與 Content-Type
。伺服器據此決定,該實際請求是否被允許。
啥時觸發預檢請求?
- 發送跨域請求時,請求頭中包含了一些非簡單請求的頭信息,如自定義頭(custom header)
- 發送跨域請求時,使用了 PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH等請求方法
“大姐你聽懂了嗎?所以這不是 bug,趕緊把它關掉吧!”
大姐漏出了澄澈的目光,好吧
4 上案例
這下測試大姐終於半信半疑地關閉了Bug。
5 假如世上沒有測試大姐
我說假如啊!你的測試老大姐就是說:我不懂你說的這些,我不管,反正我現在想看到的是在瀏覽器裡面只有一次網路請求,你自己看著辦吧,bug 我留在這了,你自己處理!
愛!瀏覽器廠商為了保證安全性,禁止了跨域,可最終還是程式員承受了所有優化的代價!
本文由博客一文多發平臺 OpenWrite 發佈!