0,背景
当前服务器有两个使用go语言开发的项目,一个负责提供RESTful API - server0,一个负责当web服务器提供页面 - server1。那么问题就来了,假设server0监听:9090端口,server1监听:9191端口,那么server1提供的页面里边如果用ajax访问server0提供的API则会有跨域问题。
如果服务器上假设了nginx那很简单,把server0和server1都藏在nginx后边当backend,ajax和页面都走:8080那就没问题了。但是在本地开发机(windows系统)上又不想大费周章的架个nginx,所以就有了本文的解决方案,ajax请求也走server1,然后server1把所有ajax请求路由到server0。
1,实施
两个server都用了gin框架,所以到谷歌搜了一下,还真有方法,原始代码是:
router.POST("/api/v1/endpoint1", ReverseProxy()
func ReverseProxy() gin.HandlerFunc {
target := "localhost:3000"
return func(c *gin.Context) {
director := func(req *http.Request) {
req.URL.Scheme = "http"
req.URL.Host = target
req.Host = target
}
proxy := &httputil.ReverseProxy{Director: director}
proxy.ServeHTTP(c.Writer, c.Request)
}
}
代码很简单,完成的工作是把/api/v1/endpoint1这个API的POST请求全部反向代理到localhost:3000的服务上去。我们的需求是把所有API请求都反向出去,所以稍作修改:
func ReverseProxy() gin.HandlerFunc {
target := config.MainConfig.Config["backend_target"]
return func(c *gin.Context) {
director := func(req *http.Request) {
req.URL.Scheme = "http"
req.URL.Host = target
req.Host = target
}
proxy := &httputil.ReverseProxy{Director: director}
proxy.ServeHTTP(c.Writer, c.Request)
}
}
apiPrefix := "/api/v1"
dumpParam := []string{apiPrefix, "a", "b", "c", "d", "e", "f", "g","h"}
for i := range []int{1,2,3,4,5,6,7,8,9,10} {
urlPattern := strings.Join(dumpParam[0:i], "/:")
r.POST(urlPattern, ReverseProxy())
r.GET(urlPattern, ReverseProxy())
}
其实如果gin能支持"/api/v1/*"这种形式的话,代码会更简单。