func (p *ProxySrv) dynamicReverseProxy() *httputil.ReverseProxy {
	roundTripper := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
			return (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
				DualStack: true,
			}).DialContext(ctx, network, addr)
		},
		MaxIdleConns:          100,
		DisableKeepAlives:     false,
		IdleConnTimeout:       10 * time.Second,
		ResponseHeaderTimeout: 30 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
		ExpectContinueTimeout: 1 * time.Second,
	}
	transport := &transport{RoundTripper: roundTripper}
	httpProxy := &httputil.ReverseProxy{
		Director:  p.dynamicDirector,
		Transport: transport,
	}
	return httpProxy
}
get ReverseProxy Http Handler
package libra
import (
	"bytes"
	"context"
	"crypto/tls"
	"github.com/zhuCheer/libra/balancer"
	"github.com/zhuCheer/libra/logger"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strings"
	"time"
)
type ProxySrv struct {
	ProxyAddr    string
	customHeader map[string]string
}
var (
	Logger      = logger.NoopLogger{}
	errorHeader = "x-libra-err"
	version     = "v0.0.1"
	githubUrl   = "https://github.com/zhuCheer/libra"
)
func NewHttpProxySrv(addr string, header map[string]string) *ProxySrv {
	if header == nil {
		header = map[string]string{}
	}
	return &ProxySrv{
		ProxyAddr:    addr,
		customHeader: header,
	}
}
func (p *ProxySrv) SetLoggerLevel(level string) {
	Logger.SetLevel(level)
}
func (p *ProxySrv) Start() error {
	proxyHttpMux := http.NewServeMux()
	Logger.Info("start proxy server bind " + p.ProxyAddr)
	proxyHttpMux.Handle("/", p.httpMiddleware(p.dynamicReverseProxy()))
	proxyServer := &http.Server{
		Addr:    p.ProxyAddr,
		Handler: proxyHttpMux,
	}
	err := proxyServer.ListenAndServe()
	panic(err)
}
func (p *ProxySrv) RegistSite(domain, loadType, scheme string) *ProxySrv {
	balancer.RegistTargetNoAddr(domain, loadType, scheme)
	return p
}
func (p *ProxySrv) GetSiteInfo(domain string) (*balancer.RegistNode, error) {
	info, err := balancer.GetSiteInfo(domain)
	return info, err
}
func (p *ProxySrv) AddAddr(domain string, addr string, weight uint32) *ProxySrv {
	info, err := balancer.GetSiteInfo(domain)
	if err == nil {
		info.Balancer.AddAddr(addr, weight)
	}
	return p
}
func (p *ProxySrv) DelAddr(domain string, addr string) {
	info, err := balancer.GetSiteInfo(domain)
	if err == nil {
		info.Balancer.DelAddr(addr)
	}
}
func (p *ProxySrv) FlushProxy(domain string) {
	balancer.FlushProxy(domain)
}
func (p *ProxySrv) ChangeLoadType(domain, loadType string) {
	balancer.ChangeLoadType(domain, loadType)
}
func (p *ProxySrv) ResetCustomHeader(header map[string]string) {
	p.customHeader = map[string]string{}
	p.customHeader = header
}
func (p *ProxySrv) httpMiddleware(handler *httputil.ReverseProxy) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		for key, value := range p.customHeader {
			w.Header().Add(key, value)
		}
		w.Header().Set("X-LIBRA-VERSION", version)
		w.Header().Set("X-LIBRA-CODE", githubUrl)
		handler.ServeHTTP(w, r)
	})
}
func (p *ProxySrv) dynamicDirector(req *http.Request) {
	siteInfo, err := balancer.GetSiteInfo(req.Host)
	var target *url.URL
	var proxyTarget *balancer.ProxyTarget
	for {
		if err != nil {
			req.Header.Set(errorHeader, err.Error())
			break
		}
		proxyTarget, err = siteInfo.Balancer.GetOne()
		if err != nil {
			req.Header.Set(errorHeader, err.Error())
			break
		}
		target, err = url.Parse(siteInfo.Scheme + "://" + proxyTarget.Addr)
		if err != nil {
			req.Header.Set(errorHeader, err.Error())
			break
		}
		targetQuery := target.RawQuery
		req.URL.Host = target.Host
		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
		if targetQuery == "" || req.URL.RawQuery == "" {
			req.URL.RawQuery = targetQuery + req.URL.RawQuery
		} else {
			req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
		}
		if _, ok := req.Header["User-Agent"]; !ok {
			req.Header.Set("User-Agent", "")
		}
		break
	}
	if err == nil {
		req.URL.Scheme = siteInfo.Scheme
	}
	Logger.Info("proxy to " + req.URL.String())
}