package proxy import ( "net/http" "net/http/httputil" "io/ioutil" "fmt" "strings" "bytes" "io" ) type Handler struct { } func copyHeader(dst, src http.Header) { for k, vv := range src { for _, v := range vv { dst.Add(k, v) } } } func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // we need to buffer the body if we want to read it here and send it // in the request. body, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fmt.Println("request body--start") fmt.Println(string(body)) fmt.Println("request body--stop") // you can reassign the body if you need to parse it as multipart r.Body = ioutil.NopCloser(bytes.NewReader(body)) // create a new url from the raw RequestURI sent by the client url := fmt.Sprintf("%s://%s%s", "http", r.Host, r.RequestURI) fmt.Println("-----Request-----", r.RequestURI) fmt.Println(r.Method, url) proxyReq, err := http.NewRequest(r.Method, url, bytes.NewReader(body)) // We may want to filter some headers, otherwise we could just use a shallow copy // proxyReq.Header = r.Header proxyReq.Header = make(http.Header) for h, val := range r.Header { tmp := []string{} for _, v := range val{ if h == "Accept-Encoding" && strings.Contains(v, "gzip") { continue } tmp = append(tmp, v) } proxyReq.Header[h] = tmp fmt.Println(h, ":", tmp) } httpClient := &http.Client{ CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, } resp, err := httpClient.Do(proxyReq) if err != nil { http.Error(w, err.Error(), http.StatusBadGateway) return } copyHeader(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) responseData, err := httputil.DumpResponse(resp, true) if err != nil { fmt.Println("err", err) } responseString := string(responseData) fmt.Println("-----Response-----", r.RequestURI) fmt.Println(responseString) io.Copy(w, resp.Body) defer resp.Body.Close() // legacy code }