时隔多年,业务开发需要与前端合作,而再次遇到跨域问题。这次不打算直接网上搬运解决代码,而是要搞清楚原理。(事实上这次也找不到合适的源码)。
由于历史原因,项目使用的不是原生的fasthttp,而是被封装过的一个中间件:
"github.com/qiangxue/fasthttp-routing"
在里面搜索了一段解决跨域的解决,然后无果:
// https://github.com/qiangxue/fasthttp-routing/issues/6
![在这里插入图片描述](https://www.icode9.com/i/ll/?i=2021060723414583.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI2NjQ4ODg=,size_16,color_FFFFFF,t_70)
再去 fasthttp 源码站点搜索到了以下变量:
// CORS
HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials"
HeaderAccessControlAllowHeaders = "Access-Control-Allow-Headers"
HeaderAccessControlAllowMethods = "Access-Control-Allow-Methods"
HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin"
HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers"
HeaderAccessControlMaxAge = "Access-Control-Max-Age"
HeaderAccessControlRequestHeaders = "Access-Control-Request-Headers"
HeaderAccessControlRequestMethod = "Access-Control-Request-Method"
HeaderOrigin = "Origin"
HeaderTimingAllowOrigin = "Timing-Allow-Origin"
HeaderXPermittedCrossDomainPolicies = "X-Permitted-Cross-Domain-Policies"
综合对比各网页的解决方案后,锁定在前六个变量:
HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials"
HeaderAccessControlAllowHeaders = "Access-Control-Allow-Headers"
HeaderAccessControlAllowMethods = "Access-Control-Allow-Methods"
HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin"
HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers"
HeaderAccessControlMaxAge = "Access-Control-Max-Age"
而决定我本决跨域失败的参数:“Access-Control-Allow-Headers” 。网上给出来的大多数版本的值是:
"Authorization, Content-Length, X-CSRF-Token, Token,session"
而在我的网页的request里可以看到这个字段 Access-Control-Request-Headers 的值为:
authorization, backstagetoken, content-type
事实上,也就是这个请求对应的响应字段:Access-Control-Allow-Headers 没有包含backstagetoken 和 content-type,导致失败。将backstagetoken, content-type加上以后,就成功了。而再次测试客户端已经通过 Access-Control-Max-Age 字段的值要等 172800 秒后才会再次发起OPTION跨域请求。
整体的代码如下:
router := routing.New()
router.Use(
util.WriteMicroServerAccessLog,
)
router.Use(func(c *routing.Context) error {
//origin := string(req.Request.Header.Peek("Origin"))
origin := string(c.Request.Header.Peek("Origin")) //请求头部
if origin != "" {
// CORS
c.Response.Header.Set(fasthttp.HeaderAccessControlAllowCredentials, "true")
c.Response.Header.Set(fasthttp.HeaderAccessControlAllowHeaders, "backstagetoken, content-type, Authorization, Content-Length, X-CSRF-Token, Token,session")
c.Response.Header.Set(fasthttp.HeaderAccessControlAllowMethods, "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
c.Response.Header.Set(fasthttp.HeaderAccessControlAllowOrigin, origin)
c.Response.Header.Set(fasthttp.HeaderAccessControlExposeHeaders, "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
c.Response.Header.Set(fasthttp.HeaderAccessControlMaxAge, "172800")
}
//允许类型校验
if string(c.Method()) == "OPTIONS" {
c.Abort()
}
return nil
})