【提问】

在Golang的Gin款家中,如何通过CORS解决跨域问题

【解答】

具体步骤如下:

1、服务端进行CORS头配置

在Go工程main.go文件中,增加cors的配置,代码如下。这里有两个非常重要的点需要注意:

1、cors的配置router.Use(Cors()),一定要放在router.GET()等方法之前,先执行cors配置,不然会出现cors 不生效的情况

2、设置Header时,「Access-Control-Allow-Credentials=true」和「Access-Control-Allow-Origin=“*”」有冲突,所以如果设置了「Access-Control-Allow-Credentials=true」,则「Access-Control-Allow-Origin」不能配置通配符,而需要具体写出每一个需要跨域的地址:「http://www.test.com」等

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	router := gin.Default()
	router.Use(Cors())

	router.GET("/test", func(c *gin.Context) {
		c.String(http.StatusOK, "Hello world! 这时一个基于Gin得cors跨域web服务")
	})

	router.Run(":8081")
}

// 处理跨域请求,支持options访问
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		//Access-Control-Allow-Credentials=true和Access-Control-Allow-Origin="*"有冲突
		//故Access-Control-Allow-Origin需要指定具体得跨域origin
		c.Header("Access-Control-Allow-Origin", "http://www.fullstars.com:8000")
		c.Header("Access-Control-Allow-Credentials", "true")
		c.Header("Access-Control-Allow-Headers", "content-type")
		c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE")
		//c.Header("Access-Control-Expose-Headers", "*")
		if c.Request.Method == "OPTIONS" {
			c.JSON(http.StatusOK, "")
			c.Abort()
			return
		}
		c.Next()
	}
}

代码写好后,服务端启动即可。

2、客户端请求配置

这里客户端以Vue为例(reactjs方式类似),我们使用axios来进行服务请求(axios的安装使用这里不做介绍)。
我们使用axios创建实例时,打开「withCredentials」配置(该配置为true时,才能允许进行cookie的写操作),如下:

// 引入axios
import axios from 'axios';

export const baseURL = 'http://www.test.com';

// 创建实例
const instance = axios.create({
  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL,
  // `timeout` 指定请求超时的毫秒数。
  // 如果请求时间超过 `timeout` 的值,则请求会被中断
  timeout: 1000 * 10, // 默认值是 `0` (永不超时)
  // 自定义请求头
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
  },
  // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: true,
});
3、客户端进行请求

客户端简单写一个测试请求:

test() {
	ajax({
	  url: '/test',
	  method: 'get',
	  params: {},
	})
	  .then((data) => {
	  })
	  .catch((error) => {
	  })
	  .finally(() => {
	  });
}

请求后,会发现已经可以跨域进行调用了