R·ex / Zeng


音游狗、安全狗、攻城狮、业余设计师、段子手、苦学日语的少年。

由于 gin-cors 而带来的 Bug

我最近在写一个管理系统的后端项目,用的是 Go,使用了 gin 来写服务器。跟前端本地联调的时候一直是没问题的,但直到有一天前后端部署到了 Test 环境开始测试,发现所有的 GET 请求都没问题,但所有的 POST 和 PUT 请求都 403 了。

我再三检查了一下 Request Authorizor Middleware,确认了并没问题(不然前端本地访问也不会正常),而且如果确实因为权限问题而 403,是有错误信息的,但现在没有任何信息。于是我连上服务器开始看 Log,发现无论是 gin 的 Access Log 还是 Error Log,都没有关于 POST 和 PUT 的访问记录,说明很有可能请求都没能坚持到这儿。

后来与同事一起找原因,同事使用 Postman 手动发了个请求,成功了,于是我也用 Postman 抓了个包发出去,但还是 403,整个 src 中返回 http.StatusBadRequest 的地方只有 Request Authorizor Middleware 一处……

实在找不到问题,于是我将 Request Header 一个个删掉再发送,直到删掉了 Origin 字段,发现可以了……

于是就注意到了 gin-cors 这个包。我们这个后端项目需要接受从 http://localhost:3000 传来的跨域请求,以方便前端调试。要支持跨域的话,首选 gin-cors。按照官方文档的说法,写起来应该很简单:

import "github.com/itsjamie/gin-cors"

// Initialize a new Gin router
router := gin.New()

// Apply the middleware to the router (works with groups too)
router.Use(cors.Middleware(cors.Config{
    Origins:        "http://localhost:3000",
    Methods:        "GET, PUT, POST, DELETE",
    RequestHeaders: "Origin, Authorization, Content-Type",
    // ....
}))

然后我在想,如果 gin-cors 足够智障,不管是否跨域,只要看到 Header 中有 Origin 字段,就从设置的 Origins 中判断,如果没通过就 403,就会出现这样的问题。于是我将 Test 环境的域名加到了 Origins,部署,可以了……

至于为什么连 Access Log 都没有,因为记录 Log 的代码在 gin-cors 的后面……

版权声明:除文章开头有特殊声明的情况外,所有文章均可在遵从 CC BY 4.0 协议的情况下转载。

这是我们共同度过的

第 1114 天