Golang反向代理 请求体修改 返回体修改 请求头修改 IP修改 添加连接池,定义错误信息

Golang反向代理 请求体修改 返回体修改 请求头修改 IP修改 添加连接池,定义错误信息

package main //反向代理ip设置连接池设置 import ( "bytes" "io/ioutil" "log" "math/rand" "net" "net/http" "net/http/httputil" "net/url" "regexp" "strconv" "strings" "time" ) var addr = "127.0.0.1:2001" func main() { rs1 := ":2002" url1, err1 := url.Parse(rs1) if err1 != nil { log.Println(err1) } urls := []*url.URL{url1} proxy := NewMultipleHostsReverseProxy(urls) log.Println("Starting httpserver at " + addr) log.Fatal(http.ListenAndServe(addr, proxy)) } var transport = &http.Transport{ DialContext: (&net.Dialer{ Timeout: 30 * time.Second, //连接超时 KeepAlive: 30 * time.Second, //长连接超时时间 }).DialContext, MaxIdleConns:100,//最大空闲连接 IdleConnTimeout: 90 * time.Second, //空闲超时时间 TLSHandshakeTimeout: 10 * time.Second, //tls握手超时时间 ExpectContinueTimeout: 1 * time.Second,//100-continue 超时时间 } func NewMultipleHostsReverseProxy(targets []*url.URL) *httputil.ReverseProxy { //请求协调者对请求进行设置 修改 director := func(req *http.Request) { //url_rewrite //127.0.0.1:2002/dir/abc ==> 127.0.0.1:2003/base/abc ?? //127.0.0.1:2002/dir/abc ==> 127.0.0.1:2002/abc //127.0.0.1:2002/abc ==> 127.0.0.1:2003/base/abc re, _ := regexp.Compile("^/dir(.*)"); req.URL.Path = re.ReplaceAllString(req.URL.Path, "$1") //随机负载均衡 targetIndex := rand.Intn(len(targets)) target := targets[targetIndex] targetQuery := target.RawQuery req.URL.Scheme = target.Scheme req.URL.Host = target.Host // url地址重写:重写前:/aa 重写后:/base/aa 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", "user-agent") } //只在第一代理中设置此header头 req.Header.Set("X-Real-Ip", req.RemoteAddr) } //更改内容 modifyFunc := func(resp *http.Response) error { //请求以下命令:curl :2002/error if resp.StatusCode != 200 { //获取内容 oldPayload, err := ioutil.ReadAll(resp.Body) if err != nil { return err } // body 追加内容 newPayload := []byte("StatusCode error:" + string(oldPayload)) resp.Body = ioutil.NopCloser(bytes.NewBuffer(newPayload)) // head 修改追加内容 resp.ContentLength = int64(len(newPayload)) resp.Header.Set("Content-Length", strconv.FormatInt(int64(len(newPayload)), 10)) } return nil } //错误回调 :关闭real_server时测试,错误回调 errFunc := func(w http.ResponseWriter, r *http.Request, err error) { http.Error(w, "ErrorHandler error:"+err.Error(), 500) } return &httputil.ReverseProxy{ Director: director, //请求内容 Transport:transport, //连接池 ModifyResponse: modifyFunc, //返回修改 ErrorHandler: errFunc, //报错执行 } } func singleJoiningSlash(a, b string) string { aslash := strings.HasSuffix(a, "/") bslash := strings.HasPrefix(b, "/") switch { case aslash && bslash: return a + b[1:] case !aslash && !bslash: return a + "/" + b } return a + b }