package main import ( "io/ioutil" "log" "net" "net/http" "net/http/httputil" "net/url" "regexp" "strings" "time" ) type LoggingTransport struct { transport *http.Transport } func (l *LoggingTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { log.Println("Request:", req) resp, err = l.transport.RoundTrip(req) if err != nil { log.Println("Err:", err) invalidContentLengthRegexp := regexp.MustCompile(`http: Request.ContentLength=\d+ with Body length \d+`) if invalidContentLengthRegexp.MatchString(err.Error()) { return &http.Response{ Body: ioutil.NopCloser(strings.NewReader("")), StatusCode: 400, // HTTP: Bad Request }, nil } return resp, err } return resp, err } func main() { connectTimeout, headerTimeout := 1*time.Second, 1*time.Second backendURL, _ := url.Parse("http://localhost:8081") proxy := httputil.NewSingleHostReverseProxy(backendURL) proxy.Transport = &LoggingTransport{&http.Transport{ Dial: func(network, address string) (net.Conn, error) { log.Println("Dialling...", network, address, connectTimeout) return net.DialTimeout(network, address, connectTimeout) }, ResponseHeaderTimeout: headerTimeout, }} log.Fatal(http.ListenAndServe(":9080", proxy)) }