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.