跨域問題可從前后兩端分開排查:
前端:Vue + axios
axios 請求頭使用 'Content-Type': 'application/json'桅锄,
并且在Header中設置了 Authorization 字段用于傳遞 Token,
參數(shù)未經(jīng) Qs 轉碼铁蹈,
使用以下代碼測試登錄接口:
// 為方便操作泄私,已將 axios 實例掛載到 this.$axios 上
this.$axios.post('/signin', {account: '', password: ''})
.then(res => {
console.log('成功:', res)
})
.catch(err => {
console.log('失敗: ', err)
})
出現(xiàn)如下錯誤:
Access to XMLHttpRequest at 'http://127.0.0.1:8080/api/v1/signin' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
同時 POST 請求變成了 OPTIONS 請求粥烁,并且返回404棚瘟,如下圖:
這里有兩個問題拄丰,一個是為什么 POST 變成了 OPTIONS府树?URL 路徑?jīng)]錯,為什么又會返回 404料按?
POST 變 OPTIONS 問題涉及復雜跨域請求奄侠,符合以下任意一個條件的請求就算復雜請求:
- 使用了除 HEAD、GET载矿、POST之外的請求方法垄潮;
- 頭部字段不超出 Accept、Accept-Language闷盔、Content-Language弯洗、Last-Event-ID、Content-Type逢勾,并且 Content-Type 的值只限于 application/x-www-form-urlencoded牡整、multipart/form-data、text/plain溺拱;
由于設置的 Authorization 字段逃贝,Content-Type 也設置為了 application/json谣辞,因此這個請求算復雜跨域請求,會在正式通信前增加一次 OPTIONS 查詢請求沐扳,稱為"預檢"請求(preflight request)潦闲,用于向服務器請求權限等信息,預檢請求被成功響應后迫皱,才會發(fā)出真實的 POST 請求歉闰。
可為什么 OPTIONS 請求返回 404 呢?
通過上面的錯誤說明及分析卓起,答案應該很清晰了和敬,就是服務端路由未對 OPTIONS 類型請求做出響應,導致 404 的情況戏阅。
后端:GoFrame
GoFrame 的路由代碼如下:
func init() {
s := g.Server()
// 綁定 CORS 中間件
s.BindMiddleware("/api/*", middleware.CORS)
s.Group("/api", func(group *ghttp.RouterGroup) {
...
// 重點:此路由僅支持 POST
group.POST("/signin", userController, "SignIn")
}
}
/signin 的路由指定了請求方式為 POST昼弟,自然無法響應其他類型的請求,使用如下方式定義倒是可響應所有類型的請求:
group.ALL("/signin", userController, "SignIn")
這樣就使該路由支持所有的請求方法奕筐,但需要在控制器的 SignIn 方法中做判斷需要響應哪些類型的請求舱痘,很繁瑣,不推薦此方式离赫。
其實只要在 CORS 中間件中對 OPTIONS 請求做統(tǒng)一響應即可芭逝,上代碼:
// CORS 允許接口跨域請求
func CORS(r *ghttp.Request) {
// 使用框架默認的 CORS 設置
r.Response.CORSDefault()
if r.Method == "OPTIONS" {
r.Response.WriteStatusExit(http.StatusOK)
} else {
r.Middleware.Next()
}
}
另外需要注意的是,使用 GoFrame 框架渊胸,CORS 中間件要在全局添加旬盯,如果在路由組中添加,同樣會出現(xiàn) OPTIONS 請求 404 的情況翎猛,而且中間件的代碼在請求過程中未執(zhí)行胖翰,原因暫不清楚,還需要多了解下框架切厘。
本文描述的跨域問題是在網(wǎng)頁上使用 Vue + axios 時出現(xiàn)的萨咳,使用 Postman 工具調(diào)試則一切正常,這里記錄下排查過程和解決方法疫稿,希望能幫到有需要的童鞋培他,有任何問題可以在評論里一起討論下。