Add HTTPCompressor for HTTP Content-Encoding negotiation.

This commit is contained in:
Andy Balholm 2019-04-30 14:53:06 -07:00
parent f00818cf36
commit 5c318f9037
3 changed files with 46 additions and 0 deletions

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module github.com/andybalholm/brotli
go 1.12
require github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721

2
go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw=
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=

View File

@ -1,8 +1,12 @@
package brotli
import (
"compress/gzip"
"errors"
"io"
"net/http"
"github.com/golang/gddo/httputil"
)
const (
@ -114,3 +118,38 @@ func (w *Writer) Close() error {
func (w *Writer) Write(p []byte) (n int, err error) {
return w.writeChunk(p, operationProcess)
}
type nopCloser struct {
io.Writer
}
func (nopCloser) Close() error { return nil }
// HTTPCompressor chooses a compression method (brotli, gzip, or none) based on
// the Accept-Encoding header, sets the Content-Encoding header, and returns a
// WriteCloser that implements that compression. The Close method must be called
// before the current HTTP handler returns.
//
// Due to https://github.com/golang/go/issues/31753, the response will not be
// compressed unless you set a Content-Type header before you call
// HTTPCompressor.
func HTTPCompressor(w http.ResponseWriter, r *http.Request) io.WriteCloser {
if w.Header().Get("Content-Type") == "" {
return nopCloser{w}
}
if w.Header().Get("Vary") == "" {
w.Header().Set("Vary", "Accept-Encoding")
}
encoding := httputil.NegotiateContentEncoding(r, []string{"br", "gzip"})
switch encoding {
case "br":
w.Header().Set("Content-Encoding", "br")
return NewWriter(w)
case "gzip":
w.Header().Set("Content-Encoding", "gzip")
return gzip.NewWriter(w)
}
return nopCloser{w}
}