使用的是标准库”net/http/httputil”

说明

  • 一定要修改Director
	proxy := &httputil.ReverseProxy{Director: func(req *http.Request) {
		req.URL.Scheme = url.Scheme
		req.URL.Host = url.Host
		req.Host = url.Host
		// fmt.Println(req.URL.String())
	}}
  • 原因:
    • 标准库里面默认的Director,可以发现它并没有修改req.Host,只是修改了req.URL.Host,而golang在req.Host为空的时候才会使用req.URL.Host,req.Host是和头部的Host是一致的,客户端发送请求的时候是会在头部携带Host,因此req.Host肯定不为空并且为代理服务器的地址,这样代理请求的时候头部的Host就不是目标服务器的地址,因此会返回404。
        proxy := &httputil.ReverseProxy{Director: func(req *http.Request) {
		req.URL.Scheme = url.Scheme
		req.URL.Host = url.Host
		req.Host = url.Host
		// fmt.Println(req.URL.String())
	}}
  • 根据项目的需求,我们服务器地址没有多余的查询参数以及需要转义的部分,因此重写的Directior中就不需要对查询参数进行处理

代码细节

const (
	httpScheme = "https"
	wsScheme   = "wss"
)

var srv *ProxyManager

// ProxyManager反向代理服务
type ProxyManager struct {
	//日志
	logger *zap.Logger
	//反向代理
	reverseProxy *httputil.ReverseProxy
	targetHost   string
}

func NewProxy() *ProxyManager {
	logger := zap.L()
	if logger == nil {
		fmt.Println("NewProxy logger is nil while it's shouldn't")
		os.Exit(-1)
	}
	targetHost := config.GetConfig("targetHost")
	if targetHost == "" {
		logger.Error("get targetUrlHttps from config failed:targetUrlHttps is empty")
		return nil
	}
	targetUrl := httpScheme + "://" + targetHost
	logger.Info(targetUrl)
	url, err := url.Parse(targetUrl)
	if err != nil {
		logger.Error("parse targetUrl failed:" + err.Error())
		return nil
	}
	proxy := &httputil.ReverseProxy{Director: func(req *http.Request) {
		req.URL.Scheme = url.Scheme
		req.URL.Host = url.Host
		req.Host = url.Host
		// fmt.Println(req.URL.String())
	}}

	return &ProxyManager{
		logger:       logger,
		reverseProxy: proxy,
		targetHost:   targetHost,
	}
}

func Run() {
	srv = NewProxy()
	if srv == nil {
		fmt.Println("ProxyManager server is nil while it's shouldn't")
		os.Exit(-1)
	}
	srv.logger.Info("ProxyManager server is running")
	//处理http请求
	http.Handle("/api/", http.HandlerFunc(srv.ProxyClientHttpRequest))
	//处理websocket请求
	http.Handle("/msg/", http.HandlerFunc(srv.ProxyClientHttpRequest))
}

func (srv *ProxyManager) ProxyClientHttpRequest(w http.ResponseWriter, r *http.Request) {
	if srv.logger == nil {
		fmt.Println("ProxyClientHttpRequest logger is nil while it's shouldn't")
		os.Exit(-1)
	}
	srv.logger.Info("-->android_local_server/proxy/proxy.go:func ProxyClientHttpRequest")
	// srv.logger.Sugar().Debugf("request:%v",r)

	srv.reverseProxy.ServeHTTP(w, r)

	srv.logger.Info("ProxyClientHttpRequest end")
}

Tags:

Comments are closed

       

粤公网安备44011302004556号