package main import ( "context" "io" "net" "net/http" "time" "github.com/fangdingjun/go-log" ) type proxy struct { transport http.RoundTripper addr string prefix string dialer *net.Dialer network string } func newProxy(addr string, prefix string) *proxy { p := &proxy{ addr: addr, prefix: prefix, dialer: &net.Dialer{Timeout: 2 * time.Second}, } if addr[0] == '/' { p.network = "unix" } else { p.network = "tcp" } p.transport = &http.Transport{ DialContext: p.dialContext, MaxIdleConns: 5, IdleConnTimeout: 30 * time.Second, } return p } func (p *proxy) dialContext(ctx context.Context, network, addr string) (net.Conn, error) { return p.dialer.DialContext(ctx, p.network, p.addr) } func (p *proxy) dial(network, addr string) (conn net.Conn, err error) { return p.dialer.Dial(p.network, p.addr) } func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { host, _, _ := net.SplitHostPort(r.RemoteAddr) r.Header.Add("X-Forwarded-For", host) r.URL.Scheme = "http" r.URL.Host = r.Host resp, err := p.transport.RoundTrip(r) if err != nil { log.Print(err) w.WriteHeader(http.StatusBadGateway) w.Write([]byte("

502 Bad Gateway

")) return } header := w.Header() for k, v := range resp.Header { for _, v1 := range v { header.Add(k, v1) } } w.WriteHeader(resp.StatusCode) io.Copy(w, resp.Body) resp.Body.Close() }