最近在項目偶然發現使用第三方文件管理系統上傳文件時,上傳請求會發送兩次。發現第一個是預檢請求OPTIONS
。
老早就知道HTTP請求方法有OPTIONS
,但從來沒使用過,一時引起了興趣,遂查閱了相關資料。
什麼是OPTIONS請求
OPTIONS
請求也被稱爲預檢請求,主要用於獲知服務端支持的HTTP請求方法。跨域資源共享(CORS
)標準新增了一組 HTTP 首部字段,配合預檢請求可獲知服務器允許哪些源站通過瀏覽器有權限訪問哪些資源。
請求頭
在OPTIONS
的請求頭中主要有幾個關鍵字段:Access-Control-Request-Method
、Access-Control-Request-Headers
、Origin
。
請求頭字段 | 作用 |
---|---|
Access-Control-Request-Method |
告知服務器實際請求所使用的HTTP 方法 |
Access-Control-Request-Headers |
告知服務器實際請求所攜帶的自定義首部字段 |
Origin |
發起請求的源站 |
在本次請求中,實際採用的post請求,自定義頭部字段有uthorization
,login-type
,x-requested-with
,如下圖所示:
響應頭
在OPTIONS
的響應頭中比較重要的有五個字段:Access-Control-Allow-Methods
、Access-Control-Allow-Credentials
、Access-Control-Allow-Origin
、Access-Control-Request-Headers
、Access-Control-Request-Headers
響應頭字段 | 作用 |
---|---|
Access-Control-Allow-Methods |
服務端允許的請求方法,包括GET /HEAD /PUT /PATCH /POST /DELETE |
Access-Control-Allow-Credentials |
允許跨域攜帶cookie (跨域請求時XMLHttpRequest.withCredentials 爲true ,預檢時響應頭該字段必須設置爲true ,才能攜帶cookie ) |
Access-Control-Allow-Origin |
允許跨域請求的域名,自行在服務端配置一些信任的域名白名單 |
Access-Control-Request-Headers |
客戶端請求所攜帶的自定義首部字段content-type |
Access-Control-Max-Age |
本次預檢請求的有效期,單位爲秒,在此期間不用發出另一條預檢請求。可用於優化 |
在本次請求中,其響應頭如下:
預檢請求的自動發起
除主動發起預檢請求外,在跨域請求時經常會遇到自動發起預檢請求。實際上在MDNCORS功能描述中有這樣寫到:
規範要求,對那些可能對服務器數據產生副作用的
HTTP
請求方法(特別是GET
以外的 HTTP 請求,或者搭配某些 MIME 類型的POST
請求),瀏覽器必須首先使用 OPTIONS 方法發起一個預檢請求(preflight request
),從而獲知服務端是否允許該跨域請求。服務器確認允許之後,才發起實際的 HTTP 請求。
當發生以下情況時,客戶端就會自動發起OPTIONS預檢請求
- 使用以下任一HTTP 方法:
PUT
/DELETE
/CONNECT
/OPTIONS
/TRACE
/PATCH
- 設置了以下頭部字段以外的自定義字段:
Accept/Accept-Language
/Content-Language
/Content-Type
/DPR
/Downlink
/Save-Data
/Viewport-Width
/Width
Content-Type
的值不屬於下列之一:application/x-www-form-urlencoded
、multipart/form-data
、text/plain
- 請求中的任意
XMLHttpRequestUpload
對象均沒有註冊任何事件監聽器;XMLHttpRequestUpload
對象可以使用XMLHttpRequest.upload
屬性訪問。 - 請求中沒有使用
ReadableStream
對象
按照上面的規則,因爲本次實際請求設置了自定義字段故觸發了預檢請求。