Support for SSE logs httpxtra.LogWriter is now exported and therefore allows others to update the used Bytes when they hijack the ResponseHandler.
diff --git a/examples/sse/sse.go b/examples/sse/sse.go index 2c1e6cf..e02ebc1 100644 --- a/examples/sse/sse.go +++ b/examples/sse/sse.go
@@ -42,12 +42,19 @@ } defer conn.Close() // Play the movie, frame by frame + nbytes := 0 for n, f := range frames[sf:] { + nbytes += len(f.Buf) m := &sse.MessageEvent{Id: strconv.Itoa(n + 1), Data: f.Buf} - e := sse.SendEvent(buf, m) - if e != nil { - // usually a broken pipe error + if err = sse.SendEvent(buf, m); err != nil { + // Usually a broken pipe error. // log.Println(e.Error()) + + // We update the bytes written to the handler so + // logging works fine. + if lw, ok := w.(*httpxtra.LogWriter); ok { + lw.Bytes += nbytes + } break } time.Sleep(f.Time)
diff --git a/httpxtra/handler.go b/httpxtra/handler.go index 3da7da7..3992346 100644 --- a/httpxtra/handler.go +++ b/httpxtra/handler.go
@@ -32,7 +32,7 @@ // details. func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { t := time.Now() - lw := logWriter{w: w} + lw := LogWriter{ResponseWriter: w} if h.Handler == nil { h.Handler = http.DefaultServeMux } @@ -47,6 +47,6 @@ } h.Handler.ServeHTTP(&lw, r) if h.Logger != nil { - h.Logger(r, t, lw.status, lw.bytes) + h.Logger(r, t, lw.Status, lw.Bytes) } }
diff --git a/httpxtra/log.go b/httpxtra/log.go index c7f4971..00f7f92 100644 --- a/httpxtra/log.go +++ b/httpxtra/log.go
@@ -15,44 +15,44 @@ // LoggerFunc are functions called by httpxtra.Handler at the end of each request. type LoggerFunc func(r *http.Request, created time.Time, status, bytes int) -type logWriter struct { - w http.ResponseWriter - bytes int - status int +type LogWriter struct { + ResponseWriter http.ResponseWriter + Bytes int + Status int } -func (lw *logWriter) Header() http.Header { - return lw.w.Header() +func (lw *LogWriter) Header() http.Header { + return lw.ResponseWriter.Header() } -func (lw *logWriter) Write(b []byte) (int, error) { - if lw.status == 0 { - lw.status = http.StatusOK +func (lw *LogWriter) Write(b []byte) (int, error) { + if lw.Status == 0 { + lw.Status = http.StatusOK } - n, err := lw.w.Write(b) - lw.bytes += n + n, err := lw.ResponseWriter.Write(b) + lw.Bytes += n return n, err } -func (lw *logWriter) WriteHeader(s int) { - lw.w.WriteHeader(s) - lw.status = s +func (lw *LogWriter) WriteHeader(s int) { + lw.ResponseWriter.WriteHeader(s) + lw.Status = s } -func (lw *logWriter) Flush() { - lw.w.(http.Flusher).Flush() +func (lw *LogWriter) Flush() { + lw.ResponseWriter.(http.Flusher).Flush() } -func (lw *logWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { - if lw.status == 0 { - lw.status = http.StatusOK +func (lw *LogWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + if lw.Status == 0 { + lw.Status = http.StatusOK } // TODO: Check. Does it break if the server don't support hijacking? - return lw.w.(http.Hijacker).Hijack() + return lw.ResponseWriter.(http.Hijacker).Hijack() } -func (lw *logWriter) CloseNotify() <-chan bool { - return lw.w.(http.CloseNotifier).CloseNotify() +func (lw *LogWriter) CloseNotify() <-chan bool { + return lw.ResponseWriter.(http.CloseNotifier).CloseNotify() } // ApacheCommonLog returns an Apache Common access log string.