commit 40e21be5e324b5c29711edf8893aa86b3993b08c Author: Stephen Searles Date: Sun Sep 4 21:02:05 2016 -0700 initial commit diff --git a/httpdebug.go b/httpdebug.go new file mode 100644 index 0000000..fb7daab --- /dev/null +++ b/httpdebug.go @@ -0,0 +1,82 @@ +package httpdebug + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "unicode" +) + +// Wrap returns an http handler that serves h while logging requests and responses to stderr. +func Wrap(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Println(r.Method, r.URL.Path, r.Proto) + + hBuf := &bytes.Buffer{} + r.Header.Write(hBuf) + log.Println(hBuf.String()) + + requestBuf := &bytes.Buffer{} + responseBuf := &bytes.Buffer{} + + defer r.Body.Close() + + r.Body = ioutil.NopCloser(io.TeeReader(r.Body, requestBuf)) + + h.ServeHTTP(rw{ + ResponseWriter: w, + w: responseBuf, + }, r) + + if requestBuf.Len() > 1024 { + trimmed := &bytes.Buffer{} + io.CopyN(trimmed, requestBuf, 128) + requestBuf = trimmed + } + + log.Println() + log.Println(logsafe(requestBuf.String())) + + hBuf.Reset() + w.Header().Write(hBuf) + log.Println(hBuf.String()) + + responseBuf = trim(responseBuf, 128) + + log.Println() + log.Println(logsafe(responseBuf.String())) + }) +} + +type rw struct { + http.ResponseWriter + w io.Writer +} + +func (rw rw) Write(b []byte) (int, error) { + rw.w.Write(b) + return rw.ResponseWriter.Write(b) +} + +func logsafe(str string) string { + buf := &bytes.Buffer{} + + for _, r := range str { + if unicode.IsPrint(r) || unicode.IsSpace(r) { + fmt.Fprintf(buf, "%c", r) + } else { + fmt.Fprintf(buf, "%x", r) + } + } + + return buf.String() +} + +func trim(b *bytes.Buffer, n int) *bytes.Buffer { + trimmed := &bytes.Buffer{} + io.CopyN(trimmed, b, int64(n)) + return trimmed +}