-
-
Save bryfry/09a650eb8aac0fb76c24 to your computer and use it in GitHub Desktop.
| package main | |
| import ( | |
| "compress/gzip" | |
| "io" | |
| "net/http" | |
| "strings" | |
| ) | |
| // Gzip Compression | |
| type gzipResponseWriter struct { | |
| io.Writer | |
| http.ResponseWriter | |
| } | |
| func (w gzipResponseWriter) Write(b []byte) (int, error) { | |
| return w.Writer.Write(b) | |
| } | |
| func Gzip(handler http.Handler) http.Handler { | |
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { | |
| handler.ServeHTTP(w, r) | |
| return | |
| } | |
| w.Header().Set("Content-Encoding", "gzip") | |
| gz := gzip.NewWriter(w) | |
| defer gz.Close() | |
| gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w} | |
| handler.ServeHTTP(gzw, r) | |
| }) | |
| } |
This gist is currently the second google result for "golang gzip http" and the first google result for some related terms.
About content-length
If your upstream writer sets Content-Length, this will result in the wrong (smaller) length being passed to the client. The middleware should remove any Content-Length header set by the upstream writer.
- This cannot be done in the
Gzip()function since the handler hasn't been called yet. - You could either overwrite
WriteHeader, or, check if headers have been sent in the first call toWriteand remove theContent-Lengthheader then. - Tracking state of this process necessitates converting from value receiver to pointer receiver.
About sync.Pool
Performance of regularly creating gzip writers is non-optimal. The gzip writer should be kept in a sync.Pool for reuse to minimise GC pressure.
I reached out to the owner of the gist to fix the update.
Is there any further example of this gzip compression that also using the sync.Pool as per @mappu said ?
Here's an updated version if anyone's interested: https://gist.github.com/CJEnright/bc2d8b8dc0c1389a9feeddb110f822d7
In the case of serving a file, would it be an option to look for an already compressed version of the file?
For max compression:
gzip.NewWriterLevel(w, gzip.BestCompression)
Content negotiation is overrated. Make way for CONTENT DICTATORSHIP!
Pure gold, was just seeking for a solution and found this 😄
Created a package for this: https://github.com/TelephoneTan/GoHTTPGzipServer
Content negotiation is overrated. Make way for CONTENT DICTATORSHIP!