Created
September 16, 2014 15:48
-
-
Save corylanou/7f5e9db83624cf23f209 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package http | |
import ( | |
"bytes" | |
"compress/gzip" | |
"net/http" | |
"strings" | |
) | |
type gzipFilter struct { | |
http.ResponseWriter | |
buffer bytes.Buffer | |
} | |
func (w *gzipFilter) Write(b []byte) (int, error) { | |
return w.buffer.Write(b) | |
} | |
func GzipFilter(fn http.HandlerFunc) http.HandlerFunc { | |
return func(w http.ResponseWriter, r *http.Request) { | |
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { | |
w.Header().Set("Content-Encoding", "gzip") | |
filter := &gzipFilter{ResponseWriter: w} // envelope the writer | |
fn(filter, r) // render the thing we're wrapping / fill our buffer | |
// set Content-Type if underlying fn has't (they usually should) | |
if w.Header().Get("Content-Type") == "" { | |
content := filter.buffer.Bytes() | |
w.Header().Set("Content-Type", http.DetectContentType(content)) | |
} | |
// clear Content-Length if underlying fn has set it (they generally do) | |
if w.Header().Get("Content-Length") != "" { | |
w.Header().Del("Content-Length") | |
} | |
zipper := gzip.NewWriter(w) | |
defer zipper.Close() | |
filter.buffer.WriteTo(zipper) | |
} else { | |
fn(w, r) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Generally you'd want to provide a http.Handler wrapper (takes a Handler, returns a Handler), as that, rather than http.HandlerFunc, is the common currency of http serving in Go.
If you had a GzipFilterer, then GzipFilter could be backwards-compatibly implemented as: