【Go】复杂请求情况下post变成options请求后台处理方法
背景
有群友在使用gin作为服务端后台,给vue前端处理跨域请求时候遇到点问题。前端使用Axios发送Post请求时候增加了自定义的Header,导致违反了简单请求要求自动变成了复杂请求,因此请求失败。 n作为服务端后台,给vue前端处理跨域请求时候遇到点问题。前端使用Axios发送Post请求时候增加了自定义的Header,导致违反了简单请求要求自动变成了复杂请求,因此请求失败。
原因
由于Axios将简单请求(单次post)请求变成了二次请求,即先发一次options
请求去判断域是否被允许,再发送真实请求post
得到结果。
而我们后台正常的跨域处理仅是针对简单请求增加了允许域通过
origin := c.Request.Header.Get("Origin")
c.Header("Access-Control-Allow-Origin", origin)
或者
c.Header("Access-Control-Allow-Origin", "*")
对于复杂请求需要增加对options
方法的处理,解决代码请看下一节
关于跨域的简单请求和复杂请求介绍可以看以下这篇文章CORS跨域请求(简单请求与复杂请求)
关于跨域标准可以看CORS
解决方法
增加中间件,添加options
方法的处理
if method == "OPTIONS" {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization") //自定义 Header
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")
c.AbortWithStatus(http.StatusNoContent) // 截获处理,并响应成功即可
}
添加完整gin的中间件文件
//gin/middleware/cors.go
//
// 模块名称: Gin框架中间件-允许跨域
// 模块描述: 处理跨域请求,支持options访问
// 创建时间: 20181009
//
package middleware
import (
"net/http"
"github.com/gin-gonic/gin"
)
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
origin := c.Request.Header.Get("Origin")
if origin != "" {
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization") //自定义 Header
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")
}
if method == "OPTIONS" {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization") //自定义 Header
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")
c.AbortWithStatus(http.StatusNoContent)
}
c.Next()
}
}
应用中间件
package main
import(
"gin/middleware"
"github.com/gin-gonic/gin"
)
func main(){
gin.SetMode(gin.ReleaseMode)
engine = gin.Default()
//绑定中间件
engine.Use(middleware.Cors())
}