12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- package main
- import (
- "bufio"
- "compress/flate"
- "compress/gzip"
- "errors"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "strings"
- )
- type writeResetter interface {
- io.Writer
- Reset(io.Writer)
- }
- type compressResponseWriter struct {
- writeResetter
- http.ResponseWriter
- }
- func (w *compressResponseWriter) WriteHeader(c int) {
- w.ResponseWriter.Header().Del("Content-Length")
- w.ResponseWriter.WriteHeader(c)
- }
- func (w *compressResponseWriter) Header() http.Header {
- return w.ResponseWriter.Header()
- }
- func (w *compressResponseWriter) Write(b []byte) (int, error) {
- h := w.ResponseWriter.Header()
- if h.Get("Content-Type") == "" {
- h.Set("Content-Type", http.DetectContentType(b))
- }
- h.Del("Content-Length")
- return w.writeResetter.Write(b)
- }
- func (w *compressResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
- h, ok := w.ResponseWriter.(http.Hijacker)
- if !ok {
- return nil, nil, errors.New("compress response does not implement http.Hijacker")
- }
- conn, bufrw, err := h.Hijack()
- if err == nil {
- w.writeResetter.Reset(ioutil.Discard)
- }
- return conn, bufrw, err
- }
- func CompressHandler(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- L:
- for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") {
- switch strings.TrimSpace(enc) {
- case "gzip":
- w.Header().Set("Content-Encoding", "gzip")
- w.Header().Add("Vary", "Accept-Encoding")
- gw := gzip.NewWriter(w)
- defer gw.Close()
- w = &compressResponseWriter{
- writeResetter: gw,
- ResponseWriter: w,
- }
- break L
- case "deflate":
- w.Header().Set("Content-Encoding", "deflate")
- w.Header().Add("Vary", "Accept-Encoding")
- fw, _ := flate.NewWriter(w, flate.DefaultCompression)
- defer fw.Close()
- w = &compressResponseWriter{
- writeResetter: fw,
- ResponseWriter: w,
- }
- break L
- }
- }
- h.ServeHTTP(w, r)
- })
- }
|