解决gin跨域问题.md

2022/6/13 Go

# 老大难的跨域问题

我们在做前后端分离的项目,时常会听到跨域问题。经常看到有人的文章标题写着: 前端支持跨域,但显然也只是个噱头而已。

跨域的概念,本人才疏学浅,就不多说了。大家有兴趣可以搜搜相关的介绍。

# 为什么来卷go

由于Mdnice官方仓库已经很久没有维护了,个人的文章又多如牛毛,在没有目录和搜索功能,官方忽略文件夹相关issue的情况下,我决定自己做一个超级低配版的mdnice,虽然我厚颜无耻地叫它mdnice-plus。

加之也觉得自己2年左右没复习go了,需要再练练go,所以后端打算用gin+gorm来完成了。

今天就聊一聊在go的web框架gin里面怎么解决跨域问题,以及在实践过程中踩的坑

大概已经抄了mdnice一小部分功能了,差个图床和目录就差不多好了。它大概长这样:

还不太完善,有一些样式也没优化到位,说实话还是mdnice好用更多

# 解决方案(如果不生效请直接看踩坑指南)

  • 民间版本 ⭐⭐⭐⭐

    民间版本指的是非官方的版本,其实解决跨域无非是需要设置response header中的allow相关数据,所以在官方没有支持的情况下出了个民间版。

    来看看大概版的:

// 文章转自知乎: https://zhuanlan.zhihu.com/p/228881482
package middleware

import (
	"github.com/gin-gonic/gin"
	"net/http"
)
func Cors() gin.HandlerFunc {
	return func(context *gin.Context) {
		method := context.Request.Method
		context.Header("Access-Control-Allow-Origin", "*")
		context.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token")
		context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
		context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		context.Header("Access-Control-Allow-Credentials", "true")
		if method == "OPTIONS" {
			context.AbortWithStatus(http.StatusNoContent)
		}
		context.Next()
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

用法很简单,使用app.Use(Cors())

  • 官方版本 ⭐⭐⭐⭐⭐

    官方封装了一个gin-contrib/cors包,里面提供了cors.Config,可以让大家配置相关的跨域选项,简单用法如下:

import (
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)

func main() {
	app := gin.New()
	app.Use(cors.Default())

}
1
2
3
4
5
6
7
8
9
10

比民间版本更推荐的原因,是代码量特别少,看起来和app.Use(log)这样的代码很接近。

# 踩坑指南

由于之前用的是iris这个web框架,所以对gin不是太了解。

如果app.Use(middleware)放在路由注册之后,那么这个接口将不为跨域接口,也就是说app.Use跨域的时候,也是有讲究的。

这点很多文章都没有说(可能大家都明白这个?)所以有时候我配置了发现跨域没生效。

比如我这样写代码:

这样就会报错了,因为cors是最后才添加的。

但也有好处,如果我把需要登录的接口都放到app.Use(auth)之后,写接口的时候就方便许多,不需要额外处理了。

由于博主的go水平一般般,虚心接受大家提出的建议/意见~大家也要来卷go的话遇到跨域问题,可以来参考参考这篇文章=3=