diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 17428002..dc5ea6aa 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -67,7 +67,7 @@ }, { "ImportPath": "github.com/gorilla/handlers", - "Rev": "0e84b7d810c16aed432217e330206be156bafae0" + "Rev": "60c7bfde3e33c201519a200a4507a158cc03a17b" }, { "ImportPath": "github.com/gorilla/mux", diff --git a/Godeps/_workspace/src/github.com/gorilla/handlers/.travis.yml b/Godeps/_workspace/src/github.com/gorilla/handlers/.travis.yml index 825dc3f2..354b7f8b 100644 --- a/Godeps/_workspace/src/github.com/gorilla/handlers/.travis.yml +++ b/Godeps/_workspace/src/github.com/gorilla/handlers/.travis.yml @@ -1,8 +1,8 @@ language: go go: - - 1.0 - 1.1 - 1.2 - 1.3 + - 1.4 - tip diff --git a/Godeps/_workspace/src/github.com/gorilla/handlers/README.md b/Godeps/_workspace/src/github.com/gorilla/handlers/README.md index 9be93705..a340abe0 100644 --- a/Godeps/_workspace/src/github.com/gorilla/handlers/README.md +++ b/Godeps/_workspace/src/github.com/gorilla/handlers/README.md @@ -1,6 +1,52 @@ gorilla/handlers ================ -[![Build Status](https://travis-ci.org/gorilla/handlers.png?branch=master)](https://travis-ci.org/gorilla/handlers) +[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers) [![Build Status](https://travis-ci.org/gorilla/handlers.svg?branch=master)](https://travis-ci.org/gorilla/handlers) + +Package handlers is a collection of handlers (aka "HTTP middleware") for use +with Go's `net/http` package (or any framework supporting `http.Handler`), including: + +* `LoggingHandler` for logging HTTP requests in the Apache [Common Log + Format](http://httpd.apache.org/docs/2.2/logs.html#common). +* `CombinedLoggingHandler` for logging HTTP requests in the Apache [Combined Log + Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by + both Apache and nginx. +* `CompressHandler` for gzipping responses. +* `ContentTypeHandler` for validating requests against a list of accepted + content types. +* `MethodHandler` for matching HTTP methods against handlers in a + `map[string]http.Handler` +* `ProxyHeaders` for populating `r.RemoteAddr` and `r.URL.Scheme` based on the + `X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded` + headers when running a Go server behind a HTTP reverse proxy. +* `CanonicalHost` for re-directing to the preferred host when handling multiple + domains (i.e. multiple CNAME aliases). + +Other handlers are documented [on the Gorilla +website](http://www.gorillatoolkit.org/pkg/handlers). + +## Example + +A simple example using `handlers.LoggingHandler` and `handlers.CompressHandler`: + +```go +import ( + "net/http" + "github.com/gorilla/handlers" +) + +func main() { + r := http.NewServeMux() + + // Only log requests to our admin dashboard to stdout + r.Handle("/admin", handlers.LoggingHandler(os.Stdout, http.HandlerFunc(ShowAdminDashboard))) + r.HandleFunc("/", ShowIndex) + + // Wrap our server with our gzip handler to gzip compress all responses. + http.ListenAndServe(":8000", handlers.CompressHandler(r)) +} +``` + +## License + +BSD licensed. See the included LICENSE file for details. -*Warning:* This package is a work in progress and the APIs are subject to change. -Consider this a v0 project. diff --git a/Godeps/_workspace/src/github.com/gorilla/handlers/compress.go b/Godeps/_workspace/src/github.com/gorilla/handlers/compress.go index 81202bbc..3d90e191 100644 --- a/Godeps/_workspace/src/github.com/gorilla/handlers/compress.go +++ b/Godeps/_workspace/src/github.com/gorilla/handlers/compress.go @@ -15,6 +15,7 @@ import ( type compressResponseWriter struct { io.Writer http.ResponseWriter + http.Hijacker } func (w *compressResponseWriter) Header() http.Header { @@ -30,6 +31,8 @@ func (w *compressResponseWriter) Write(b []byte) (int, error) { return w.Writer.Write(b) } +// CompressHandler gzip compresses HTTP responses for clients that support it +// via the 'Accept-Encoding' header. func CompressHandler(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { L: @@ -42,10 +45,17 @@ func CompressHandler(h http.Handler) http.Handler { gw := gzip.NewWriter(w) defer gw.Close() + h, hok := w.(http.Hijacker) + if !hok { /* w is not Hijacker... oh well... */ + h = nil + } + w = &compressResponseWriter{ Writer: gw, ResponseWriter: w, + Hijacker: h, } + break L case "deflate": w.Header().Set("Content-Encoding", "deflate") @@ -54,10 +64,17 @@ func CompressHandler(h http.Handler) http.Handler { fw, _ := flate.NewWriter(w, flate.DefaultCompression) defer fw.Close() + h, hok := w.(http.Hijacker) + if !hok { /* w is not Hijacker... oh well... */ + h = nil + } + w = &compressResponseWriter{ Writer: fw, ResponseWriter: w, + Hijacker: h, } + break L } } diff --git a/Godeps/_workspace/src/github.com/gorilla/handlers/handlers.go b/Godeps/_workspace/src/github.com/gorilla/handlers/handlers.go index 23a738da..c3c20e5b 100644 --- a/Godeps/_workspace/src/github.com/gorilla/handlers/handlers.go +++ b/Godeps/_workspace/src/github.com/gorilla/handlers/handlers.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -/* -Package handlers is a collection of handlers for use with Go's net/http package. -*/ package handlers import ( @@ -29,7 +26,7 @@ import ( // available methods. // // If the request's method doesn't match any of its keys the handler responds with -// a status of 406, Method not allowed and sets the Allow header to a comma-separated list +// a status of 405, Method not allowed and sets the Allow header to a comma-separated list // of available methods. type MethodHandler map[string]http.Handler @@ -65,12 +62,7 @@ type combinedLoggingHandler struct { func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { t := time.Now() - var logger loggingResponseWriter - if _, ok := w.(http.Hijacker); ok { - logger = &hijackLogger{responseLogger: responseLogger{w: w}} - } else { - logger = &responseLogger{w: w} - } + logger := makeLogger(w) url := *req.URL h.handler.ServeHTTP(logger, req) writeLog(h.writer, req, url, t, logger.Status(), logger.Size()) @@ -78,19 +70,31 @@ func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { t := time.Now() - var logger loggingResponseWriter - if _, ok := w.(http.Hijacker); ok { - logger = &hijackLogger{responseLogger: responseLogger{w: w}} - } else { - logger = &responseLogger{w: w} - } + logger := makeLogger(w) url := *req.URL h.handler.ServeHTTP(logger, req) writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size()) } +func makeLogger(w http.ResponseWriter) loggingResponseWriter { + var logger loggingResponseWriter = &responseLogger{w: w} + if _, ok := w.(http.Hijacker); ok { + logger = &hijackLogger{responseLogger{w: w}} + } + h, ok1 := logger.(http.Hijacker) + c, ok2 := w.(http.CloseNotifier) + if ok1 && ok2 { + return hijackCloseNotifier{logger, h, c} + } + if ok2 { + return &closeNotifyWriter{logger, c} + } + return logger +} + type loggingResponseWriter interface { http.ResponseWriter + http.Flusher Status() int Size() int } @@ -130,6 +134,13 @@ func (l *responseLogger) Size() int { return l.size } +func (l *responseLogger) Flush() { + f, ok := l.w.(http.Flusher) + if ok { + f.Flush() + } +} + type hijackLogger struct { responseLogger } @@ -144,6 +155,17 @@ func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) { return conn, rw, err } +type closeNotifyWriter struct { + loggingResponseWriter + http.CloseNotifier +} + +type hijackCloseNotifier struct { + loggingResponseWriter + http.Hijacker + http.CloseNotifier +} + const lowerhex = "0123456789abcdef" func appendQuoted(buf []byte, s string) []byte {