boilerplate-go/core/appserver/gzip.go

63 lines
1.3 KiB
Go

package appserver
import (
"compress/gzip"
"net/http"
"sync"
)
type gzipResponseWriter struct {
http.ResponseWriter
w *gzip.Writer
statusCode int
headerWritten bool
}
var (
pool = sync.Pool{
New: func() interface{} {
w, _ := gzip.NewWriterLevel(nil, gzip.BestSpeed)
return &gzipResponseWriter{
w: w,
}
},
}
)
func (gzr *gzipResponseWriter) WriteHeader(statusCode int) {
gzr.statusCode = statusCode
gzr.headerWritten = true
if gzr.statusCode != http.StatusNotModified && gzr.statusCode != http.StatusNoContent {
gzr.ResponseWriter.Header().Del("Content-Length")
gzr.ResponseWriter.Header().Set("Content-Encoding", "gzip")
}
gzr.ResponseWriter.WriteHeader(statusCode)
}
func (gzr *gzipResponseWriter) Write(b []byte) (int, error) {
if _, ok := gzr.Header()["Content-Type"]; !ok {
// If no content type, apply sniffing algorithm to un-gzipped body.
gzr.ResponseWriter.Header().Set("Content-Type", http.DetectContentType(b))
}
if !gzr.headerWritten {
// This is exactly what Go would also do if it hasn't been written yet.
gzr.WriteHeader(http.StatusOK)
}
return gzr.w.Write(b)
}
func (gzr *gzipResponseWriter) Flush() {
if gzr.w != nil {
gzr.w.Flush()
}
if fw, ok := gzr.ResponseWriter.(http.Flusher); ok {
fw.Flush()
}
}