問題
使用axios請求接口時,出現了發出兩次請求的情況;一個是請求OPTIONS,一個是正常的POST請求;查資料發現與跨域請求有關。
概念
MDN中有提到:
出於安全原因,瀏覽器限制從腳本內發起的跨源HTTP請求。
跨域資源共享標准允許在下列場景中使用跨域 HTTP 請求:
- 前文提到的由
XMLHttpRequest或 Fetch 發起的跨域 HTTP 請求。 - Web 字體 (CSS 中通過
@font-face使用跨域字體資源), 因此,網站就可以發布 TrueType 字體資源,並只允許已授權網站進行跨站調用。 - WebGL 貼圖
- 使用
drawImage將 Images/video 畫面繪制到 canvas - 樣式表(使用 CSSOM)
而在頁面中通過src或者href嵌入cdn文件或者圖片之類的可以直接引入不會遵循CORS。
跨域資源共享標准新增了一組 HTTP 首部字段,允許服務器聲明哪些源站通過瀏覽器有權限訪問哪些資源。另外,規范要求,對那些可能對服務器數據產生副作用的 HTTP 請求方法(特別是 GET 以外的 HTTP 請求,或者搭配某些 MIME 類型的 POST 請求),瀏覽器必須首先使用 OPTIONS 方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求。服務器確認允許之后,才發起實際的 HTTP 請求。
簡單請求不會觸發CORS預檢請求,而非簡單請求則會觸發
若請求滿足所有下述條件,則該請求可視為“簡單請求”,否則為非簡單請求:
- 使用下列方法之一:GET POST HEAD
- Fetch 規范定義了對 CORS 安全的首部字段集合,不得人為設置該集合之外的其他首部字段。該集合為:
AcceptAccept-LanguageContent-LanguageContent-Type()DPRDownlinkSave-DataViewport-WidthWidth
Content-Type的值僅限於下列三者之一:text/plainmultipart/form-dataapplication/x-www-form-urlencoded
- 請求中的任意
XMLHttpRequestUpload對象均沒有注冊任何事件監聽器;XMLHttpRequestUpload對象可以使用XMLHttpRequest.upload屬性訪問。 - 請求中沒有使用
ReadableStream對象。
解決辦法
檢查多余的請求頭部:后台管理統有登錄用戶,登錄后請求接口都會加一個自定義的頭部token,每次請求都會帶上讓后台校驗是否為當前用戶或者token是否過期,當刪除請求的token時,沒有出現預請求。正常請求一次,加上token則會再次出現兩次請求。
axios設置默認的Content-type為簡單請求規定的三者之一。
引入qs模塊,axios請求時添加qs序列化
后台設置 Access-Control-Max-Age(number) 。數值代表preflight request (預檢請求)的返回結果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被緩存多久,單位是秒。
例如:將預檢請求的結果緩存10分鍾(但該方法第一次請求還是會發起一次option)
Access-Control-Max-Age: 600
