背景

有群友在使用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())  
}

文章目录