Go中跨域Cors中间件的实现

 更新时间:2023年06月07日 11:46:54   作者:王也枉不了  
本文主要介绍了Go中跨域Cors中间件的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

通过建造者模式创建我们的跨域中间件Cors

我们了解到,当使用XMLHttpRequest发送请求时,如果浏览器发现违反了同源策略就会自动加上一个请求头 origin;

后端在接受到请求后确定响应后会在 Response Headers 中加入一个属性 Access-Control-Allow-Origin;

浏览器判断响应中的 Access-Control-Allow-Origin 值是否和当前的地址相同,匹配成功后才继续响应处理,否则报错

缺点:忽略 cookie,浏览器版本有一定要求

同时,结合项目实际,我们可以使用一个config结构体来存放我们的配置,这里可以使用建造者模式进行灵活的管理
所以cors中,我们也添加与config相同的字段
Config:

// CorsConfig 使用了建造者模式
type CorsConfig struct {
	AllowOrigins []string
	AllowMethods []string
	AllowHeaders []string
	//如果想要让客户端可以访问到其他的标头,服务器必须将它们在 Access-Control-Expose-Headers 里面列出来.eg:"Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires
	ExposeHeaders []string
	//这个响应头表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息)可以被缓存多久。
	AccessControlMaxAge string
	//告知浏览器是否可以将对请求的响应暴露给前端 JavaScript 代码。
	AccessControlAllowCredentials bool
}

Cors:

type Cors struct {
AllowOrigins []string
AllowMethods []string
AllowHeaders []string
//如果想要让客户端可以访问到其他的标头,服务器必须将它们在 Access-Control-Expose-Headers 里面列出来.eg:"Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires
ExposeHeaders []string
//这个响应头表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息)可以被缓存多久。
AccessControlMaxAge string
//告知浏览器是否可以将对请求的响应暴露给前端 JavaScript 代码。
AccessControlAllowCredentials bool
}

当然,我们的Config需要一些方法来控制字段的值

func (c *CorsConfig) AddOrigins(origins ...string) *CorsConfig {
   c.AllowOrigins = append(c.AllowOrigins, origins...)
   return c
}
func (c *CorsConfig) AddMethods(methods ...string) *CorsConfig {
   c.AllowMethods = append(c.AllowMethods, methods...)
   return c
}
func (c *CorsConfig) AddHeaders(headers ...string) *CorsConfig {
   c.AllowHeaders = append(c.AllowHeaders, headers...)
   return c
}
func (c *CorsConfig) AddExposeHeaders(exposeHeaders ...string) *CorsConfig {
   c.ExposeHeaders = append(c.ExposeHeaders, exposeHeaders...)
   return c
}
func (c *CorsConfig) SetAccessControlMaxAge(ms string) *CorsConfig {
   c.AccessControlMaxAge = ms
   return c
}
func (c *CorsConfig) SetAccessControlAllowCredentials(isAllow bool) *CorsConfig {
   c.AccessControlAllowCredentials = isAllow
   return c
}

同时,为了方便,我们可以给出一个方法来设置默认的情况

func DefaultCorsConfig() *CorsConfig {
   return &CorsConfig{
   	AllowOrigins:                  []string{"*"},
   	AllowMethods:                  []string{"POST", "POST", "GET", "OPTIONS", "PUT", "DELETE", "UPDATE"},
   	AllowHeaders:                  []string{"Authorization", "Content-Length", "X-CSRF-Token", "Token", "session", "X_Requested_With", "Accept", "Origin", "Host", "Connection", "Accept-Encoding", "Accept-Language", "DNT", "X-CustomHeader", "Keep-Alive", "User-Agent", "X-Requested-With", "If-Modified-Since", "Cache-Control", "Content-Type", "Pragma"},
   	ExposeHeaders:                 []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Cache-Control", "Content-Languge", "Caontent-Type", "Expires", "Last-Modified", "Pragma", "FooBar"},
   	AccessControlMaxAge:           "200000",
   	AccessControlAllowCredentials: true,
   }
}

最后,实现将config应用到Cors中的方法和应用Cors的设置的方法
将config应用到Cors中的方法:

func (cors *Cors) SetCorsConfig(c *CorsConfig) {
   cors.AccessControlMaxAge = c.AccessControlMaxAge
   cors.ExposeHeaders = c.ExposeHeaders
   cors.AllowOrigins = c.AllowOrigins
   cors.AllowHeaders = c.AllowHeaders
   cors.AllowMethods = c.AllowMethods
   cors.AccessControlAllowCredentials = c.AccessControlAllowCredentials
}

应用Cors的设置的方法 :

func (cors *Cors) Apply() sgin8.HandlerFunc {
   return func(context *sgin8.Context) {
   	method := context.Req.Method
   	origin := context.Req.Header.Get("Origin")
   	if origin != "" {
   		context.SetHeader("Access-Control-Allow-Origin", strings.Join(cors.AllowOrigins, ",")) // 设置允许访问所有域
   		context.SetHeader("Access-Control-Allow-Methods", strings.Join(cors.AllowMethods, ","))
   		context.SetHeader("Access-Control-Allow-Headers", strings.Join(cors.AllowHeaders, ","))
   		context.SetHeader("Access-Control-Expose-Headers", strings.Join(cors.ExposeHeaders, ","))
   		context.SetHeader("Access-Control-Max-Age", cors.AccessControlMaxAge)
   		context.SetHeader("Access-Control-Allow-Credentials", strconv.FormatBool(cors.AccessControlAllowCredentials))
   	} else {
   		log.Printf("This request haven not set the 'Origin' in Header")
   	}
   	if method == "OPTIONS" {
   		context.JSON(http.StatusOK, "Options Request!")
   	}
   	//处理请求
   	context.Next()
   }
}

当然,我们提供快速开始的方案:

func (c *CorsConfig) Build() sgin8.HandlerFunc {
	cors := &Cors{}
	cors.SetCorsConfig(c)
	return cors.Apply()
}

demo:

func main() {
	//eg1:
	r := sgin8.Default()
	config1 := sgin8.DefaultCorsConfig()
	cors1 := sgin8.Cors{}
	cors1.SetCorsConfig(config1)
	r.Use(cors1.Apply())
	//eg2
	r.Use(sgin8.DefaultCorsConfig().Build())
	//eg3
	config3 := sgin8.CorsConfig{}
	config3.SetAccessControlMaxAge("200000").SetAccessControlAllowCredentials(true).AddMethods("GET", "POST")
	r.Use(config3.Build())
	//eg4
	config4 := &sgin8.CorsConfig{}
	config4.SetAccessControlMaxAge("200000").SetAccessControlAllowCredentials(true).AddMethods("GET", "POST")
	cors4 := sgin8.Cors{}
	cors4.SetCorsConfig(config4)
	cors4.Apply()
	r.GET("/", func(c *sgin8.Context) {
		c.String(http.StatusOK, "Hello wxk\n")
	})
	// index out of range for testing Recovery()
	r.GET("/panic", func(c *sgin8.Context) {
		names := []string{"wxk"}
		c.String(http.StatusOK, names[100]) //访问不到
	})
	r.Run(":9999")
}

你也许会问为什么实现的这么繁琐,那么下文将会解释下原因!

外链:https://www.jb51.net/article/237709.htm

跨域测试:

失败情况:

失败情况

成功情况!

成功情况!

到此这篇关于Go中跨域Cors中间件的实现的文章就介绍到这了,更多相关Go跨域Cors中间件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go与Redis实现分布式互斥锁和红锁

    Go与Redis实现分布式互斥锁和红锁

    这篇文章主要介绍了Go与Redis实现分布式互斥锁和红锁,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • goland 导入github包报红问题解决

    goland 导入github包报红问题解决

    本文主要介绍了Go项目在GoLand中导入依赖标红问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-08-08
  • GO 语言学习指南

    GO 语言学习指南

    这篇文章主要介绍了GO 语言学习指南,介绍的相当全面,有需要的小伙伴参考下吧。
    2015-01-01
  • Go中sync.Once源码的深度讲解

    Go中sync.Once源码的深度讲解

    sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有所帮助
    2025-01-01
  • golang获取prometheus数据(prometheus/client_golang包)

    golang获取prometheus数据(prometheus/client_golang包)

    本文主要介绍了使用Go语言的prometheus/client_golang包来获取Prometheus监控数据,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • GO语言实现批量压缩图片和水印

    GO语言实现批量压缩图片和水印

    这篇文章主要介绍了GO语言实现批量压缩图片和水印,主要用到了github.com/nfnt/resize这个第三方库,仅仅支持JPG图片格式,有相同需求的小伙伴参考下吧。
    2015-03-03
  • Go实现替换(覆盖)文件某一行内容的示例代码

    Go实现替换(覆盖)文件某一行内容的示例代码

    本文主要介绍了Go实现替换(覆盖)文件某一行内容的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Go语言实现超时的三种方法实例

    Go语言实现超时的三种方法实例

    超时在一些业务场景里非常普遍,下面这篇文章主要给大家介绍了关于Go语言实现超时的三种方法,文中通过实例代码介绍的非常详细,对大家学习或者使用Go语言具有一定的参考学习价值,需要的朋友可以参考下
    2022-07-07
  • 解决go build不去vendor下查找包的问题

    解决go build不去vendor下查找包的问题

    这篇文章主要介绍了解决go build不去vendor下查找包的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • go variant底层原理深入解析

    go variant底层原理深入解析

    这篇文章主要为大家介绍了go variant底层原理深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11

最新评论