boilerplate-go/core/appserver/brotli.go

62 lines
1.3 KiB
Go

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