Skip to content

Instantly share code, notes, and snippets.

@marbemac
Created September 8, 2015 06:22
Show Gist options
  • Save marbemac/300c4c376171cbd27cc3 to your computer and use it in GitHub Desktop.
Save marbemac/300c4c376171cbd27cc3 to your computer and use it in GitHub Desktop.
Simple go proxy, copying body
package main
import (
"bytes"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
)
func main() {
log.Printf("Starting...")
http.HandleFunc("/", someFunc)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func someFunc(w http.ResponseWriter, r *http.Request) {
// change the request host to match the target
r.Host = "localhost:3000"
u, _ := url.Parse("http://localhost:3000")
proxy := httputil.NewSingleHostReverseProxy(u)
proxy.Transport = &myTransport{}
proxy.ServeHTTP(w, r)
}
type myTransport struct{}
func (t *myTransport) RoundTrip(request *http.Request) (*http.Response, error) {
response, err := http.DefaultTransport.RoundTrip(request)
bodyBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
// err
} else {
response.Body.Close()
// Restore the io.ReadCloser to its original state
// This is causing huge increases in memory usage.
response.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
}
// Another way to do it, with httputil.. same result, lots of memory.
// The httputil package provides a DumpResponse() func that will copy the
// contents of the body into a []byte and return it. It also wraps it in an
// ioutil.NopCloser and sets up the response to be passed on to the client.
// _, err = httputil.DumpResponse(response, true)
// if err != nil {
// return nil, err
// }
return response, err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment