最近在用uni-app開發項目時,發現一個之前沒注意到的點,當我發送POST請求的時候,在NetWork可以看到在發送正式的POST請求時,會先發送一個OPTIONS請求,OPTIONS請求后才會發送真正的POST請求
這其實是瀏覽器對復雜跨域請求的一種處理方式,在真正發送請求之前,會先進行一次OPTIONS預請求,以確定服務器響應是否正確,是否能接受真正的請求,如果在options請求之后獲取到的響應是拒絕性質的,例如500等http狀態,那么它就會停止第二次的真正請求的訪問。
其實最終是因為瀏覽器對簡單跨域請求和復雜跨域請求的處理區別。
XMLHttpRequest會遵守同源策略(same-origin policy). 也即腳本只能訪問相同協議/相同主機名/相同端口的資源, 如果要突破這個限制, 那就是所謂的跨域, 此時需要遵守跨域資源共享標准CORS(Cross-Origin Resource Sharing)機制。
瀏覽器將CORS請求分為兩類:簡單請求(simple request)和非簡單請求(not-simple-request)。
簡單請求瀏覽器請求不會觸發預檢請求,而非簡單請求會觸發預檢請求。這兩種方式怎么區分?
同時滿足下列以下條件,就屬於簡單請求,否則屬於非簡單請求(參考HTTP訪問控制(CORS))
1.請求方式只能是:GET、POST、HEAD 2.HTTP請求頭限制這幾種字段(不得人為設置該集合之外的其他首部字段): 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 4.請求中的任意XMLHttpRequestUpload 對象均沒有注冊任何事件監聽器;XMLHttpRequestUpload 對象可以使用 XMLHttpRequest.upload 屬性訪問。 5.請求中沒有使用 ReadableStream 對象。
非簡單請求 會在正式通信之前,增加一次HTTP請求,稱之為預檢請求。瀏覽器會先發起OPTIONS方法到服務器,以獲知服務器是否允許該實際請求。
由此可知,若要我們的請求滿足簡單請求就可以避免發起OPTIONS請求了。
但是
1、我們系統請求中除了GET/POST還有PUT,DELETE,不能滿足
2,我們系統有做業務模塊權限,請求頭里需要帶有用戶驗證信息,第二點也不滿足
3,我們的Content-Type絕大多數是application/json,還是不滿足
然后只能寄希望於減少發起OPTIONS請求的次數,也就是說還是會用,但不是每次都用,查到的方法如下:
后端在請求的返回頭部添加:
Access-Control-Max-Age:(number) 。數值代表preflight request (預檢請求)的返回結果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被緩存多久,單位是秒。
例如:將預檢請求的結果緩存10分鍾:
Access-Control-Max-Age: 600
不同瀏覽器有不同的上限。在Firefox中,上限是24h(即86400秒),而在Chromium 中則是10min(即600秒)。Chromium 同時規定了一個默認值 5 秒。
如果值為 -1,則表示禁用緩存,每一次請求都需要提供預檢請求,即用OPTIONS請求進行檢測。
Access-Control-Max-Age方法對完全一樣的url的緩存設置生效,多一個參數也視為不同url。也就是說,如果設置了10分鍾的緩存,在10分鍾內,所有請求第一次會產生options請求,第二次以及第二次以后就只發送真正的請求了。
轉載自:https://blog.csdn.net/xiaoxiong_jiaxin/article/details/88060663