Go 使用 httputil.ReverseProxy 创建代理

640 阅读1分钟
  • pattern:源路径
  • target:目标路径(转发到的url)

若希望将/api代理到http://localhost/v1/api,则pattern/apitargethttp://localhost/v1/api

这里使用echo框架

// ServeProxy 代理服务
func ServeProxy(e *echo.Echo, pattern string, target string) {
	targetUrl, err := url.Parse(target)
	if err != nil {
		log.Println(err)
		return
	}
	proxy := &httputil.ReverseProxy{
                // 重写 request.Out.URL 为目标路径
		Rewrite: func(request *httputil.ProxyRequest) {
			request.Out.URL.Scheme = targetUrl.Scheme
			request.Out.URL.Host = targetUrl.Host
			request.Out.URL.Path = path.Join(targetUrl.Path, strings.TrimPrefix(request.In.URL.Path, pattern))
		},
                // 对响应进行处理,可不写
		ModifyResponse: func(response *http.Response) error {
			response.Header.Del("X-Frame-Options")
			response.Header.Del("X-XSS-Protection")
			response.Header.Del("X-Content-Type-Options")
			// 若后端已经配置了这些响应头,则删掉,防止重复配置
			response.Header.Del("Access-Control-Allow-Origin")
			response.Header.Del("Access-Control-Allow-Methods")
			response.Header.Del("Access-Control-Allow-Headers")
			response.Header.Del("Access-Control-Allow-Credentials")
			response.Header.Del("Access-Control-Max-Age")
			response.Header.Del("Access-Control-Expose-Headers")
			return nil
		},
	}
        // 处理所有前缀为 pattern 的路由,若使用标准库,可写成 pattern+"/"
	e.Any(pattern+"*", func(context echo.Context) error {
                // 若使用标准库,则直接传res,req
		proxy.ServeHTTP(context.Response(), context.Request())
		return nil
	})
}