在前后台分離的項目中,經常會遇到瀏覽器想服務端發送一個post/patch請求,實際上產生了兩個請求,一個是Option,另一個才是真實的Post/Patch請求, 而get請求則不會產生Options請求。

造成此種問題的原因是瀏覽器處理跨域的機制,下面來掰扯一下為什么會出現Option請求。
Options請求出現的情況有兩種:
1、獲取后台服務器支持的HTTP的通信方式
2、對跨域請求進行preflight request(預檢請求)。
預檢請求首先需要向另外一個域名的資源發送一個Http Options的請求頭,以檢測實際發送的請求是否是安全的。options請求是瀏覽器自發起的preflight request(預檢請求)。
preflight request請求報文中有兩個需要關注的首部字段:
(1)Access-Control-Request-Method:告知服務器實際請求所使用的HTTP方法;
(2)Access-Control-Request-Headers:告知服務器實際請求所攜帶的自定義首部字段。
同時服務器也會添加origin header,告知服務器實際請求的客戶端的地址。服務器基於從預檢請求獲得的信息來判斷,是否接受接下來的實際請求。
服務器所返回的Access-Control-Allow-Methods首部字段將所有允許的請求方法告知客戶端,返回將所有Access-Control-Request-Headers首部字段將所有允許的自定義首部字段告知客戶端。此外,服務器端可返回Access-Control-Max-Age首部字段,允許瀏覽器在指定時間內,無需再發送預檢請求,直接用本次結果即可。
在我們開發過程中出現的瀏覽器自發起的options請求就是上面的第二種情況。實際上,跨域請求中的”復雜請求”發出前會進行一次方法是options的preflight request。
二、當跨域請求是簡單請求時不會進行preflight request,只有復雜請求才會進行preflight request。
跨域請求分兩種:簡單請求、復雜請求;
符合以下任一情況的就是復雜請求:
1.使用方法put/delete/patch/post;
2.發送json格式的數據(content-type: application/json)
3.請求中帶有自定義頭部;
其他情況則可理解為是簡單請求。
為什么跨域的復雜請求需要preflight request?
復雜請求可能對服務器數據產生副作用。例如delete或者put,都會對服務器數據進行修改,所以在請求之前都要先詢問服務器,當前網頁所在域名是否在服務器的許可名單中,服務器允許后,瀏覽器才會發出正式的請求,否則不發送正式請求。
