寫這篇文章的背景是由於以前遇到的,在跨域的狀況下經過 axios 發起的 get 請求正常,post 請求會在正式請求發送以前先發送一個 opstions 請求,然後端接口沒有兼容 options,致使 404 的狀況。前端
而在解決這個問題時帶着好奇心順帶查了一下,給本身補充了些知識點。ios
簡單講,從 JavaScript
代碼發起的 XMLHttpRequest
請求能夠分爲兩種:json
不會觸發CORS預檢
的請求,而是直接向服務端發送請求,什麼是 CORS預檢
我們後面說,其匹配的規則大體以下:axios
GET
、 HEAD
、 POST
中的一種ACCEPT
Accept-Language
Content-Language
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type (值僅限text/plain,multipart/form-data,application/x-www-form-urlencoded)
XMLHttpRequestUpload
對象沒有註冊任何事件監聽ReadableStream
對象在發送正式請求以前,會先發起一個 OPTIONS
預檢請求到服務器,以獲知服務器是否容許該實際請求,若不容許,則再也不發送請求,其匹配規則以下:後端
PUT
、 DELETE
、 CONNECT
、 OPTIONS
、 TRACE
、 PATCH
之一CORS安所有首字段集合
以外的字段XMLHttpRequestUpload
對象註冊了任意事件監聽器ReadableStream
對象在跨域請求中,若服務端返回了正確的跨域響應部首:Access-Control-Allow-Origin
、Access-Control-Allow-Method
、Access-Control-Allow-Headers
, 則跨域請求能正常獲取數據。api
根據以上了解的知識點,跟進遇到的問題,發現 axios 的請求部首 Content-Type
的值默認爲 application/json;charset=utf-8
,且 POST
請求數據爲 json
格式,故進行 POST
請求會先發出預檢請求,若服務端對預檢請求的響應爲不支持,則請求終止。跨域
根據上面分析出的緣由,如下列舉兩種解決方案:安全
使服務端接口支持 OPTIONS
方法,且對跨域預檢請求的請求部首進行完整的響應匹配,代表服務器將接受後續的實際請求,則實際請求將被正常響應。服務器
跨域時將請求轉換爲簡單請求:cookie
Content-Type
設爲 application/x-www-form-urlencoded
POST
請求數據,方式有如下兩種:
URLSearchParams
生成POST
請求的數據qs
庫的 stringify
api 對請求數據進行轉換(若請求數據中某個字段的值爲引用類型,須要先經過 JSON.stringify 處理,以防止服務端沒法識別)例子:
/* 經過 qs 模塊處理請求數據*/
import axios from 'axios'
import qs from 'qs'
axios.defaults.withCredentials = true // 若跨域請求須要帶 cookie 身份識別
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
// 請求攔截器
axios.interceptors.request.use(req => {
// 對 post 請求數據進行處理
if (req.method === 'post') {
Object.keys(req.data).forEach(item => {
!isPrimeval(req.data[item]) && (req.data[item] = JSON.stringify(req.data[item]))
})
req.data = qs.stringify(req.data)
}
return req
}, error => {
// 請求出錯時處理
return Promise.reject(error)
})
or
/* 經過 URLSearchParams 生成 POST 請求數據 */
import axios from 'axios'
async function anInterface (url, params = {}) {
let data = new URLSearchParams()
for(let key in params) {
data.append(params[key])
}
const res = await axios.post(url, data)
// 處理數據
return res.data
}
複製代碼
經過以上方式便可將 POST
預檢請求轉換爲簡單請求,其好處不言而喻,對於多個 POST
請求而言,能夠減小一半的請求數量,且在一些服務端比較不能改動的場景更爲適用。
以上爲本次文章全部內容,如有問題,望指正;若需轉載,望註明出處