前端跨域是一個老生常談的話題,前端必備的技能,網上相關介紹及解決方案紹多如牛毛,作者限於學識也講不出太過深入的見解,故此本文只是記錄一次解決跨域的post請求的小文,如果能幫助遇到相同問題的朋友,那也是極好的。行文或有錯漏,歡迎指正。
一.背景介紹
本人寫的一個vue仿貓眼電影個人練手小專案,使用的貓眼線上的api介面,使用本地代理開發時毫無異常,之後部署上線,為了解決跨域問題,我使用了nginx反向代理轉發對貓眼api的請求,大部分介面沒問題,但是有個post的請求介面被瀏覽器block了,如下圖所示的紅果果報錯(線上bug已修復,當時沒有儲存截圖,下圖是本地模擬的bug)
對此的常規解決方案當然就是輸入問題,google一番了,在一堆搜尋結果中找尋要找的那個解決方案。 如果google一下立馬有了解決方案,那當然是不可能的,作者也不會專門寫下此文。
二.解決思路
過程是曲折的,有了此文,那麼結果當然是完美解決了。
1.初步認識
雖然作者的英文很渣,但是報錯的原因看幾個關鍵詞也能猜出是跨域出了問題,具體的原因嘛,是因為預請求沒有通過控制訪問檢查,更具體的原因是預請求不允許重定向。
關鍵詞 preflight request
對此我是懵逼的,當然解決bug的過程,也是學習的過程,我便踏上了蒐羅相關文件瞭解preflight request是何方神聖。
2.查詢文件
為什麼跨域的post請求區分為簡單請求和非簡單請求和content-type相關?
前端 | 淺談preflight request 是從簡書上找到的對preflight request的科普文件,感興趣的朋友可以去看看,感謝此文的作者。
閱讀了前面提到的前端 | 淺談preflight request一文,針對出現此類的bug,我試著提取了幾個關鍵點
2.1為什麼要發預檢請求
preflight request是為確保伺服器是否允許發起對伺服器資料產生副作用的HTTP請求方法,而預先由瀏覽器發起OPTIONS方法的一個預檢請求,如果允許就傳送真實的請求,如果不允許則直接拒絕發起真實請求。
2.2首先介紹不會觸發預檢請求的方法
- GET
- HEAD
- POST
僅當POST方法的Content-Type值等於下列之一才算做簡單需求
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
2.3觸發預檢請求的方法
簡單起見,我們姑且認為除了上述羅列的不會觸發預檢請求的情況,其他情況下都會預先傳送OPTIONS進行預請求。
preflight request不允許重定向
get post head當header有自定義屬性時也會傳送options,詳見文末後記
三.嘗試解決
上面鋪墊分析了這麼多,我們來看看錯誤請求頭,如下圖,post觸發了瀏覽器傳送預檢請求OPTIONS方法,而返回的是重定向狀態碼是302,和上圖報錯資訊及preflight request相關解釋完全對應,那麼答案就很明確了,因為我們這裡使用了axios,而axios的post方法Content-Type預設是application/json; charset=utf-8;所以如何避免post觸發預檢請求的關鍵就是使用上述Content-Type的三個任一值,application/x-www-form-urlencoded才是最大淫家。
行文至此,差不多也解決了,饒了那麼大一圈,就只需修改一行配置引數,是不是有種想撞牆的感覺?初次寫文感覺詞窮了,考慮不周或者需要補充的地方,歡迎大家提出來探討一下。
後記補充
1. 經@摔炮指點補充:get post head當header有自定義屬性時也會傳送options
本著求實的態度,我進行了測試,自定義了屬性 'X-GET-PREFILGHT_TEST': 'check preflight by customize headers Attributes',確實如@摔炮所言,get到了新姿勢,感謝。 報錯資訊及請求頭等資訊如下: