Skip to content

Instantly share code, notes, and snippets.

@hdorio
Created June 13, 2017 13:12
Show Gist options
  • Save hdorio/4546d2c9cf218cdcfefd6b6f9ba7fc8f to your computer and use it in GitHub Desktop.
Save hdorio/4546d2c9cf218cdcfefd6b6f9ba7fc8f to your computer and use it in GitHub Desktop.
reverse proxy qui dump la reponse du service dans un fichier
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
_ "net/http/pprof"
"net/url"
"os"
"strings"
"time"
)
type myTransport struct {
// Uncomment this if you want to capture the transport
// CapturedTransport http.RoundTripper
}
func (t *myTransport) RoundTrip(request *http.Request) (*http.Response, error) {
reqBody, err := httputil.DumpRequestOut(request, true)
log.Print(string(reqBody))
if err != nil {
// copying the request body did not work
return nil, err
}
response, rtErr := http.DefaultTransport.RoundTrip(request)
// or, if you captured the transport
// response, err := t.CapturedTransport.RoundTrip(request)
ts := time.Now()
if response != nil {
// 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.
resBody, err := httputil.DumpResponse(response, true)
if err != nil {
// copying the response body did not work
return nil, err
}
// You may want to check the Content-Type header to decide how to deal with
// the body. In this case, we're assuming it's text.
log.Print(string(resBody))
tss := ts.Format(time.RFC3339Nano)
dirname := fmt.Sprint("./log/", ts.Format("2006-01/"))
addr1 := request.RemoteAddr
addr2 := request.Header.Get("X-Forwarded-For")
addr2 = strings.Replace(addr2, " ", "", -1)
path := strings.Replace(request.URL.Path, "/", "-", -1)
filename := fmt.Sprint(dirname, tss, "_", addr1, "_", addr2, "_", path)
content := []byte(fmt.Sprint(string(reqBody), "\n\n", string(resBody), "\n"))
if err := os.MkdirAll(dirname, 0755); err != nil {
log.Fatal("Unable to create directory", dirname)
log.Print("(", err.Error(), ")")
}
err = ioutil.WriteFile(filename, content, 0644)
if err != nil {
log.Print("Error unable to write to ", filename)
log.Print("(", err, ")")
}
return response, rtErr
} else {
log.Print(rtErr)
tss := ts.Format(time.RFC3339Nano)
dirname := fmt.Sprint("./log/", ts.Format("2006-01/"))
addr1 := request.RemoteAddr
addr2 := request.Header.Get("X-Forwarded-For")
addr2 = strings.Replace(addr2, " ", "", -1)
path := strings.Replace(request.URL.Path, "/", "-", -1)
filename := fmt.Sprint(dirname, tss, "_", addr1, "_", addr2, "_", path)
content := []byte(fmt.Sprint(string(reqBody), "\n\n", rtErr, "\n", "(no response)", "\n"))
if err := os.MkdirAll(dirname, 0755); err != nil {
log.Fatal("Unable to create directory", dirname)
log.Print("(", err.Error(), ")")
}
err = ioutil.WriteFile(filename, content, 0644)
if err != nil {
log.Print("Error unable to write to ", filename)
log.Print("(", err, ")")
}
return response, rtErr
}
}
func handler(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
//w.Header().Set("X-Header", "value")
p.Transport = &myTransport{}
p.ServeHTTP(w, r)
//log.Println(w.Header())
}
}
func main() {
log.SetOutput(os.Stdout)
log.Print("ReverseProxy Starting v1.3 (with pprof)")
log.Print("Go version 1.4.2")
port := flag.Int("p", 8080, "port to listen to")
ip := flag.String("i", "0.0.0.0", "interface to listen to")
target := flag.String("t", "http://localhost:3000", "server to proxy to")
flag.Parse()
listen := fmt.Sprint(*ip, ":", *port)
log.Println("Serving", *target, "on", "http://"+listen+"/")
remote, err := url.Parse(*target)
if err != nil {
log.Fatal(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
http.HandleFunc("/", handler(proxy))
err = http.ListenAndServe(listen, nil)
if err != nil {
log.Fatal(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment