diff options
Diffstat (limited to 'system/api/gzip.go')
-rw-r--r-- | system/api/gzip.go | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/system/api/gzip.go b/system/api/gzip.go new file mode 100644 index 0000000..9f50cf7 --- /dev/null +++ b/system/api/gzip.go @@ -0,0 +1,60 @@ +package api + +import ( + "compress/gzip" + "net/http" + "strings" + + "github.com/ponzu-cms/ponzu/system/db" +) + +// Gzip wraps a HandlerFunc to compress responses when possible +func Gzip(next http.HandlerFunc) http.HandlerFunc { + return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if db.ConfigCache("gzip_disabled").(bool) == true { + next.ServeHTTP(res, req) + return + } + + // check if req header content-encoding supports gzip + if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { + // gzip response data + res.Header().Set("Content-Encoding", "gzip") + var gzres gzipResponseWriter + if pusher, ok := res.(http.Pusher); ok { + gzres = gzipResponseWriter{res, pusher, gzip.NewWriter(res)} + } else { + gzres = gzipResponseWriter{res, nil, gzip.NewWriter(res)} + } + + next.ServeHTTP(gzres, req) + return + } + + next.ServeHTTP(res, req) + }) +} + +type gzipResponseWriter struct { + http.ResponseWriter + pusher http.Pusher + + gw *gzip.Writer +} + +func (gzw gzipResponseWriter) Write(p []byte) (int, error) { + defer gzw.gw.Close() + return gzw.gw.Write(p) +} + +func (gzw gzipResponseWriter) Push(target string, opts *http.PushOptions) error { + if opts == nil { + opts = &http.PushOptions{ + Header: make(http.Header), + } + } + + opts.Header.Set("Accept-Encoding", "gzip") + + return gzw.pusher.Push(target, opts) +} |