From e6c5ff85cbb003fa06e19dc98ff8f2c2186b4314 Mon Sep 17 00:00:00 2001 From: Brian Woods Date: Sun, 31 Mar 2019 08:17:09 -0700 Subject: [PATCH] Adds gzip to json responses --- commons/services/http_service.go | 2 +- commons/utils/gzip.go | 50 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 commons/utils/gzip.go diff --git a/commons/services/http_service.go b/commons/services/http_service.go index dbd4643..51dc14b 100644 --- a/commons/services/http_service.go +++ b/commons/services/http_service.go @@ -79,7 +79,7 @@ func (this *HttpService) Go() { }) handler := cors.Handler(this.router) - err := http.ListenAndServe(listen, handler) + err := http.ListenAndServe(listen, utils.Gzip(handler)) // QUESTION: this line is never reached utils.Error("unable to listen/serve HTTP [error=" + err.Error() + "]") diff --git a/commons/utils/gzip.go b/commons/utils/gzip.go new file mode 100644 index 0000000..77a8b13 --- /dev/null +++ b/commons/utils/gzip.go @@ -0,0 +1,50 @@ +package utils + +import ( + "compress/gzip" + "io" + "io/ioutil" + "net/http" + "strings" + "sync" +) + +var gzPool = sync.Pool{ + New: func() interface{} { + w := gzip.NewWriter(ioutil.Discard) + return w + }, +} + +type gzipResponseWriter struct { + io.Writer + http.ResponseWriter +} + +func (w *gzipResponseWriter) WriteHeader(status int) { + w.Header().Del("Content-Length") + w.ResponseWriter.WriteHeader(status) +} + +func (w *gzipResponseWriter) Write(b []byte) (int, error) { + return w.Writer.Write(b) +} + +func Gzip(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { + next.ServeHTTP(w, r) + return + } + + w.Header().Set("Content-Encoding", "gzip") + + gz := gzPool.Get().(*gzip.Writer) + defer gzPool.Put(gz) + + gz.Reset(w) + defer gz.Close() + + next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, Writer: gz}, r) + }) +}