天天看點

ajax post 變options,bug記錄——POST請求變成OPTIONS

相信大家在開發過程中經常會用到 Ajax發起請求,其中,最常見的就是post和get請求,當然也有一些不常用的,比如head、put、delete、options等。今天開發時遇到這樣一個問題,困擾了我大半天最後簡直吐血:

先是控制台那邊報錯:403 forbidden,并且提示:Invalid CORS request

仔細一看發現——請求方法竟然是OPTIONS:

ajax post 變options,bug記錄——POST請求變成OPTIONS

image.png

這就有點意思了,因為我代碼寫的明明是axios.post()!

在網上查了半天,最後終于弄明白了原因,原來對于一些post方法,浏覽器必須先發送一個“預檢請求”來确認伺服器是否允許該請求,允許的話再發送真正的請求。

并且發送的請求内容類型如果不是 application/x-www-form-urlencoded,multipart/form-data 或 text/plain 這三者的話,便會觸發options請求。

看了看我自己的代碼:

axios({

method: 'post',

url,

headers: {

'X-Requested-With': 'XMLHttpRequest',

'Content-Type': 'application/json'

},

data: JSON.stringify(param)

})

Content-Type明顯是不符合上述三種情況的,為此艱辛的嘗試了網上各種辦法。

首先是最簡單的:直接修改Content-Type——

headers: {

'content-type': 'application/x-www-form-urlencoded'

}

然而不行。

接着嘗試了網上的第二種辦法:使用 URLSearchParams轉換資料格式——

var params = new URLSearchParams()

params.append('param1', 'value1')

params.append('param2', 'value2')

很可惜,也無效。

最後我甚至加載了新的包,用來攔截請求的發起,把請求資料轉化為可用模式之後再發起請求——

首先安裝qs

npm install --save qs

然後對axios進行配置,就是在封裝axios的地方添加以下代碼:

import qs from 'qs'

// 添加響應攔截器

axios.interceptors.request.use(

config => {

if (config.method === 'post') {

config.data = qs.stringify(config.data)

}

return config

},

error => {

Promise.reject(error)

}

)

然而我還是too young too naive,這次我仍然失敗了。

ajax post 變options,bug記錄——POST請求變成OPTIONS

image.png

至此我已經瀕臨崩潰,然而——你以為我會放棄嗎!不!我一定要解決這個問題,我繼續查資料,查啊查查啊查,終于發現可以通過後端配置解決這個問題。

首先我的控制台報錯為:

ajax post 變options,bug記錄——POST請求變成OPTIONS

image.png

這意味着:

伺服器端背景接口沒有允許OPTIONS請求,導緻無法找到對應接口位址

背景方法允許OPTIONS請求,但是一些配置檔案中(如安全配置),阻止了OPTIONS請求

背景允許OPTIONS請求,并且接口也允許OPTIONS請求,但是頭部比對時出現不比對現象

那麼我就需要後端同僚——

後端允許options請求

關閉對應的安全配置

增加對應的頭部支援

servletResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with,Content-Type");

servletResponse.setHeader("Access-Control-Allow-Origin", servletRequest.getHeader("origin"));

servletResponse.setHeader("Access-Control-Allow-Methods", "POST,GET");

當然,這就是後端的任務了,更加詳細具體的請大家移步這裡——

等後端同僚改了配置之後問題成功解決,我也如釋重負,雖然修改bug時最終具體操作的并不是我們前端人員,但我還是記錄下了這個過程,希望大家遇到類似問題的時候,能夠用最快最簡單的方式解決這個問題,減少試錯的體驗。