使用的是标准库”net/http/httputil”
说明
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")
}
Comments are closed