commit
						40e21be5e3
					
				@ -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 | 
				
			||||||
 | 
					} | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue