在開發先後端分離項目時候,咱們總會面臨一個跨域問題。前端
衆所周知,在之前,跨域能夠採用代理、JSONP等方式,而在現代瀏覽器面前,咱們有了更好的選擇,CORS
。ajax
咱們能夠經過服務器端設置Access-Control-Allow-Origin
響應頭,便可使指定來源像訪問同源接口同樣訪問跨域接口。後端
在使用CORS
的時候,後臺採用token
檢驗機制,前臺發送請求必須將token
放到Request Header
中,那麼就須要傳輸自定義Header
信息,這時候細心的你必定會發現一個問題,在前端ajax請求數據的時候,有時候會向後臺一次性發送兩次請求,這兩次請求第一次無返回數據,第二次纔會返回正確數據。像下圖這個樣子,莫名多出了一個 OPTIONS
的請求:跨域
不用懷疑,這不是你的代碼有bug,也不是在請求函數中重複調用了請求,由於很明顯,兩次的 Request Method
是不同的。瀏覽器
若是你也曾因這個問題,困惑過,迷茫過,不知所因。那麼關於這個問題,我將爲你給出答案!服務器
對於CORS
跨域,有兩種不一樣的請求類型。cookie
簡單跨域請求是指知足如下兩個條件的請求。 一、HTTP方法是如下三種方法之一:app
HEAD
GET
POST
二、HTTP的頭信息不超出如下幾種字段:前後端分離
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
:只限於三個值,application/x-www-form-urlencoded、multipart/form-data、text/plain簡單跨域請求的部分響應頭以下:函數
Access-Control-Allow-Origin
(必含)- 不可省略,不然請求按失敗處理。該項控制數據的可見範圍,若是但願數據對任何人均可見,能夠填寫"*"。
Access-Control-Allow-Credentials
(可選) – 該項標誌着請求當中是否包含cookies
信息,只有一個可選值:true(必爲小寫)。若是不包含cookies
,請略去該項,而不是填寫false。這一項與XmlHttpRequest2
對象當中的withCredentials
屬性應保持一致,即withCredentials
爲true時該項也爲true;withCredentials
爲false時,省略該項不寫。反之則致使請求失敗。
Access-Control-Expose-Headers
(可選) – 該項肯定XmlHttpRequest2
對象當中getResponseHeader()
方法所能得到的額外信息。一般狀況下,getResponseHeader()
方法只能得到以下的信息:
當你須要訪問額外的信息時,就須要在這一項當中填寫並以逗號進行分隔。
任何一個不知足簡單跨域請求要求的請求,即被認爲是複雜請求,也稱做帶預檢的跨域請求。
一個複雜請求不止發送一個包含通訊內容的請求,其中最早發送的是一種**"預檢"請求**,此時做爲服務端,也須要返回**"預迴應"**做爲響應。"預檢"請求其實是對服務端的一種權限請求,只有當"預檢"請求成功返回,實際請求才開始執行。
預請求以OPTIONS
形式發送,當中一樣包含域,而且還包含了兩項CORS
特有的內容:
Access-Control-Request-Method
– 該項內容是實際請求的種類,能夠是GET、POST之類的簡單請求,也能夠是PUT、DELETE等等。Access-Control-Request-Headers
– 該項是一個以逗號分隔的列表,當中是複雜請求所使用的頭部。顯而易見,這個"預檢"請求實際上就是在爲以後的實際請求發送一個權限請求,在預迴應返回的內容當中,服務端應當對這兩項進行回覆,以讓瀏覽器肯定請求是否可以成功完成。一旦預迴應如期而至,所請求的權限也都已知足,纔會發出真實請求,攜帶真實數據。
如今問題所在已經很明顯了,那麼面對這種跨域預檢機制形成的屢次請求問題,咱們能夠在後臺設置Access-Control-Max-Age
來控制瀏覽器在多長時間內(單位s)無需在請求時發送預檢請求,從而減小沒必要要的預檢請求。
關於CORS的更細緻的問題能夠查看MDN