github.com/wlattner/mlserver@v0.0.0-20141113171038-895f261d2bfd/http_util.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "net" 6 "net/http" 7 "time" 8 9 "github.com/coreos/go-log/log" 10 ) 11 12 func writeJSONOK(w http.ResponseWriter, v interface{}) { 13 writeJSON(w, v, http.StatusOK) 14 } 15 16 func writeJSON(w http.ResponseWriter, v interface{}, status int) { 17 18 w.Header().Set("Content-Type", "application/json") 19 w.WriteHeader(status) 20 err := json.NewEncoder(w).Encode(v) 21 if err != nil { 22 http.Error(w, err.Error(), http.StatusInternalServerError) 23 } 24 } 25 26 func notAllowed(w http.ResponseWriter) { 27 http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) 28 } 29 30 //----------------------------------------------------------------------------- 31 // HTTP Request Logging 32 //----------------------------------------------------------------------------- 33 // mostly copied from github.com/wlattner/logger 34 35 // requestLogger wraps an http.Handler, logging all requests 36 func requestLogger(fn http.Handler) http.Handler { 37 return logger{fn} 38 } 39 40 type logger struct { 41 h http.Handler 42 } 43 44 func (l logger) ServeHTTP(w http.ResponseWriter, r *http.Request) { 45 start := time.Now() 46 resp := &responseLogger{w: w} 47 l.h.ServeHTTP(resp, r) 48 go printLog(r, resp.status, resp.size, time.Since(start)) 49 } 50 51 // responseLogger allows us to trap the response size and status code 52 type responseLogger struct { 53 w http.ResponseWriter 54 status int 55 size int 56 } 57 58 func (l *responseLogger) Header() http.Header { 59 return l.w.Header() 60 } 61 62 // wrap ResponseWriter.Write to capture response size 63 func (l *responseLogger) Write(b []byte) (int, error) { 64 if l.status == 0 { 65 l.status = http.StatusOK 66 } 67 size, err := l.w.Write(b) 68 l.size += size 69 return size, err 70 } 71 72 // wrap ResponseWriter.WriteHeader to capture http status code 73 func (l *responseLogger) WriteHeader(s int) { 74 l.w.WriteHeader(s) 75 l.status = s 76 } 77 78 func printLog(req *http.Request, status int, size int, d time.Duration) { 79 host, _, _ := net.SplitHostPort(req.RemoteAddr) 80 requestTime := float64(d.Nanoseconds()) / 1e6 81 // ip method path status size time 82 // 0.0.0.0 GET /api/users 200 312 34 83 log.Infof("%s %s %s %d %d %.2f", 84 host, 85 req.Method, 86 req.URL.RequestURI(), 87 status, 88 size, 89 requestTime, 90 ) 91 }