AJAX請求中出現OPTIONS請求


背景

有一個前后端分離的VUE項目來發送ajax請求, 查看Nginx日志或使用Chrome Dev Tools查看請求發送情況時, 會看到每次調后台API的請求之前, 都會發送一個OPTIONS請求, 無論API要求請求的方法是GET或POST.

為什么會發送這個OPTIONS請求? 困擾了項目組的前端同學和后端同學很久,今天正好聽他們說起這個問題,就研究了一下原理。

過程

首先, 在js代碼里是沒寫要發送OPTIONS請求的, 后台API要的請求方法不是GET就是POST, 也只發送過這兩種類型的請求.

那么, 我就以為是前台調用方式的問題, 於是去看了看代碼. 發現並沒有什么很特殊的地方。然后直接看ajax.js文件. 結果, 發現一切正常, 並沒有這種邏輯: 發送GET/POST請求之前, 先發送一個OPTIONS請求.

看來就不是前端同學寫法的問題,也不是ajax的問題,仔細對比了一下之前的代碼,發現唯一的區別就是ajax中用到了自定義的header頭。

解惑

眾所周知, ajax請求是由XMLHttpRequest對象實現的(部分低版本ID瀏覽器不是), 而XMLHttpRequest會遵守同源策略(same-origin policy). 也即腳本只能訪問相同協議/相同主機名/相同端口的資源, 如果要突破這個限制, 那就是所謂的跨域, 此時需要遵守CORS(Cross-Origin Resource Sharing)機制。

那么, 允許跨域, 不就是服務端(例如Nginx或者后端代碼)設置Access-Control-Allow-Origin: *就可以了嗎?

普通的請求確實是這樣子的, 除此之外, 還一種叫請求叫Preflighted Request(帶預檢的跨域請求)

Preflighted Request在發送真正的請求前, 會先發送一個方法為OPTIONS的預請求(Preflighted Request), 用於試探服務端是否能接受真正的請求.

如果options獲得的回應是拒絕性質的,比如404\403\500等http狀態,就會停止post、get等請求的發出。

那么, 什么情況下請求會變成Preflighted Request呢? 翻看了MDN的文檔發現如下:(文檔地址:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_request_headers)

  1. 請求方法不是GET/HEAD/POST
  2. POST請求的Content-Type並非application/x-www-form-urlencodedmultipart/form-data, 或text/plain
  3. 請求設置了自定義的header字段

舉個例子, 如果POST請求要傳輸的數據為 XML文檔, Content-Typeapplication/xmltext/xml, 則發送這個請求前會發送一個預請求,或者自定義的header字段也是一樣的道理。

 

有了上面的知識點, 再去看項目中ajax調用

可以看出, 跨域請求中設置了自定義的header字段, 所以該請求是preflighted request, 則請求前一定會發送一個OPTIONS作為預請求.

所以說, 在項目中ajax對后台API的調用, OPTIONS請求是沒辦法去掉的, 除非后台接口不再需要在請求header中設置openId

 

但是由於該項目中用戶信息是采用的JWT的方式,所以只好作罷。

 

但是由於該項目在后台中自定義了請求頻率限制的攔截器,例如限制同一個客戶端一秒內對某一個接口只能訪問1次。如果超過限制,則第二次會返回狀態碼500,不予處理。如果每次請求前都帶着一次OPTIONS請求,則該攔截器無法正常實現功能,反正會導致大批接口調用失敗的情況。

鑒於上述分析,既然前端發起請求時OPTIONS請求沒有辦法去除,那么是否可以考慮從后台攔截器進行改造。

改造后的代碼如下:

如果攔截到的請求不是項目中常規的GET或者POST請求,則該攔截器直接放行。至此,問題完美解決。希望可以幫到有類似問題的小伙伴~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM