何時會發送options請求

1 偶然的相遇——options請求

最近寫的項目,應用裏全部的ajax請求都發送了2遍。因爲新項目,基礎模塊是新搭的,因此出現一些奇葩問題也是意料之中,啊終於第一次在chrome的devTools碰見了活的options請求。 ios

1.1 第1次請求

這裏首先發送了一次額外的options請求,在瀏覽器裏看到請求request header 和 response header的信息以下:ajax

(1)預檢請求頭request header的關鍵字段:

Request Header 做用
Access-Control-Request-Method 告訴服務器實際請求所使用的 HTTP 方法
Access-Control-Request-Headers 告訴服務器實際請求所攜帶的自定義首部字段,本次實際請求首部字段中content-type爲自定義

服務器基於從預檢請求頭部得到的信息來判斷,是否接受接下來的實際請求。 chrome

(2)預檢響應頭response header的關鍵字段:

response header 做用
Access-Control-Allow-Methods 返回了服務端容許的請求,包含GET/HEAD/PUT/PATCH/POST/DELETE
Access-Control-Allow-Credentials 容許跨域攜帶cookie(跨域請求要攜帶cookie必須設置爲true)
Access-Control-Allow-Origin 容許跨域請求的域名,這個能夠在服務端配置一些信任的域名白名單
Access-Control-Request-Headers 客戶端請求所攜帶的自定義首部字段content-type

這次OPTIONS請求返回了響應頭的內容,但沒有返回響應實體response body內容。 json

1.2 第2次請求

這是原本要發送的請求,如圖所示是普通的post請求。其中Content-Typeapplication/json是這次和後端約定的請求內容格式,這個也是後面講到爲何會發送options請求的緣由之一。 axios

2 關於OPTIONS請求

從不少資料咱們能夠了解到使用OPTIONS方法對服務器發起請求,能夠檢測服務器支持哪些 HTTP 方法。可是此次咱們並無主動去發起OPTIONS請求,那OPTIONS請求爲什麼會自動發起?後端

2.1 OPTIONS請求自動發起

MDN的CORS一文中提到:跨域

規範要求,對那些可能對服務器數據產生反作用的 HTTP 請求方法(特別是 GET 之外的 HTTP 請求,或者搭配某些 MIME 類型的 POST 請求),瀏覽器必須首先使用 OPTIONS 方法發起一個預檢請求(preflight request),從而獲知服務端是否容許該跨域請求。瀏覽器

因此這個跨域請求觸發了瀏覽器自動發起OPTIONS請求,看看這次跨域請求具體觸發了哪些條件。緩存

2.2 跨域請求時,OPTIONS請求觸發條件

CORS預檢請求觸發條件 本次請求是否觸發該條件
1. 使用了下面任一HTTP 方法:
PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH 否,本次爲post請求
2. 人爲設置了如下集合以外首部字段:
Accept/Accept-Language/Content-Language/Content-Type/DPR/Downlink/Save-Data/Viewport-Width/Width 否,未設置其餘頭部字段
3. Content-Type 的值不屬於下列之一:
application/x-www-form-urlencoded、multipart/form-data、text/plain 是,爲application/json

因爲修改了Content-Type爲application/json,觸發了CORS預檢請求。安全

3 優化OPTIONS請求:Access-Control-Max-Age 或者 避免觸發

可見一旦達到觸發條件,跨域請求便會一直髮送2次請求,這樣增長的請求數是否可優化呢?答案是能夠,OPTIONS預檢請求的結果能夠被緩存。

Access-Control-Max-Age這個響應首部表示 preflight request (預檢請求)的返回結果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 能夠被緩存的最長時間,單位是秒。(MDN)

若是值爲 -1,則表示禁用緩存,每一次請求都須要提供預檢請求,即用OPTIONS請求進行檢測。

評論區的朋友提醒了,儘可能避免不要觸發OPTIONS請求,上面例子中把content-type改掉是能夠的。在其餘場景,好比跨域而且業務有自定義請求頭的話就很難避免了。如今使用的axios或者superagent等第三方ajax插件,若是出現CORS預檢請求,能夠看看默認配置或者二次封裝是否規範。

4 總結

OPTIONS請求即預檢請求,可用於檢測服務器容許的http方法。當發起跨域請求時,因爲安全緣由,觸發必定條件時瀏覽器會在正式請求以前自動先發起OPTIONS請求,即CORS預檢請求,服務器若接受該跨域請求,瀏覽器才繼續發起正式請求。

相關文章
相關標籤/搜索