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/*"這種形式的話,代碼會更簡單。