-
-
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 toWrite
and remove theContent-Length
header 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!