跨域问题可从前后两端分开排查:
前端: vue + axios
axios 请求头使用'Content-Type': 'application/json',
并且在 Header 中设置了 Authorization 字段用于传递 Token,
参数未经 Qs 转码,
使用以下代码测试登录接口:
- // 为方便操作, 已将 axios 实例挂载到 this.$axios 上
- this.$axios.post('/signin', {account: '', password:''})
- .then(res => {
- console.log('成功:', res)
- })
- .catch(err => {
- console.log('失败:', err)
- })
出现如下错误:
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, 如下图:
2.PNG
这里有两个问题, 一个是为什么 POST 变成了 OPTIONS?URL 路径没错, 为什么又会返回 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), 用于向服务器请求权限等信息, 预检请求被成功响应后, 才会发出真实的 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 请求做统一响应即可, 上代码:
- // 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 中间件要在全局添加, 如果在路由组中添加, 同样会出现 OPTIONS 请求 404 的情况, 而且中间件的代码在请求过程中未执行, 原因暂不清楚, 还需要多了解下框架.
本文描述的跨域问题是在网页上使用 Vue + axios 时出现的, 使用 Postman 工具调试则一切正常, 这里记录下排查过程和解决方法, 希望能帮到有需要的童鞋, 有任何问题可以在评论里一起讨论下.
来源: http://www.jianshu.com/p/73cd0099d42a