go中实现http请求代理转发
背景:web开发中,经常采用的是前后端分离,在后端服务采用分布式架构的情况下,请求通常都是只发到一个统一的前置服务/api网关中,然后将根据实际的请求,将调用其他服务进行实际的处理。(如下图)前置网关通常会有一些校验的中间件,进行安全校验,比如登录验证,鉴权等,而实际的业务服务通常处于内网内,用户无法直接访问,所以不需要再次做安全校验,直接处理业务逻辑。
内网服务实际的业务处理完成后将结果返回到网关,再由网关下发到用户端,这边就涉及到服务间的远程调用,而远程调用通常使用的两种方式是HTTP和RPC。接下来分析的是通过HTTP进行远程调用的方式。
假设对外服务监听在本地80端口,内部服务监听在8081端口,有这么一个请求localhost/test_proxy
,需要转发到localhost:8081/do_proxy
上进行处理,并返回结果。网关用golang
实现如下:
//对外服务定义路由
router.Use(OtherMiddlewares)//其他中间件
router.Post("/test_proxy",ReverseProxy);
//反向代理到内部服务localhost:8081
func ReverseProxy() gin.HandlerFunc {
target := "localhost:8081"
return func(c *gin.Context) {
director := func(req *http.Request) {
req.URL.Scheme = "http"
req.URL.Host = target
req.URL.Path = "/do_proxy"
// add custom headers
req.Header["my-header"] = []string{req.Header.Get("my-header")}
// delete Origin headers
delete(req.Header, "My-Header")
}
proxy := &httputil.ReverseProxy{Director: director}
proxy.ServeHTTP(c.Writer, c.Request)
}
}
这边相当于实现了一个透明代理,如果需要用户验证、鉴权等操作,可以在其他中间件中进行实现。当然可以在网关层应用上维护一个路由映射关系表
,当需要请求来时,判断是否需要走反向代理逻辑,如果要走反向代理逻辑,则反向代理到相应的url上。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。