// Gziper returns a Handler that adds gzip compression to all requests. // Make sure to include the Gzip middleware above other middleware // that alter the response body (like the render middleware). func Gziper(options ...Options) macaron.Handler { opt := prepareOptions(options) return func(ctx *macaron.Context) { if !strings.Contains(ctx.Req.Header.Get(_HEADER_ACCEPT_ENCODING), "gzip") { return } headers := ctx.Resp.Header() headers.Set(_HEADER_CONTENT_ENCODING, "gzip") headers.Set(_HEADER_VARY, _HEADER_ACCEPT_ENCODING) // We've made sure compression level is valid in prepareGzipOptions, // no need to check same error again. gz, err := gzip.NewWriterLevel(ctx.Resp, opt.CompressionLevel) if err != nil { panic(err.Error()) } defer gz.Close() gzw := gzipResponseWriter{gz, ctx.Resp} ctx.Resp = gzw ctx.MapTo(gzw, (*http.ResponseWriter)(nil)) if ctx.Render != nil { ctx.Render.SetResponseWriter(gzw) } ctx.Next() // delete content length after we know we have been written to gzw.Header().Del("Content-Length") } }
// Gzip returns a handler which will handle the Gzip compression in ServeHTTP. // Valid values for level are identical to those in the compress/gzip package. func Gzip(level int) *handler { h := &handler{} h.pool.New = func() interface{} { gz, err := gzip.NewWriterLevel(ioutil.Discard, level) if err != nil { panic(err) } return gz } return h }
// ServeHTTP wraps the http.ResponseWriter with a gzip.Writer. func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { // Skip compression if the client doesn't accept gzip encoding. if !strings.Contains(r.Header.Get(headerAcceptEncoding), encodingGzip) { next(w, r) return } // Skip compression if client attempt WebSocket connection if len(r.Header.Get(headerSecWebSocketKey)) > 0 { next(w, r) return } // Skip compression if already compressed if w.Header().Get(headerContentEncoding) == encodingGzip { next(w, r) return } // Create new gzip Writer. Skip compression if an invalid compression // level was set. gz, err := gzip.NewWriterLevel(w, h.compressionLevel) if err != nil { next(w, r) return } defer gz.Close() // Set the appropriate gzip headers. headers := w.Header() headers.Set(headerContentEncoding, encodingGzip) headers.Set(headerVary, headerAcceptEncoding) // Wrap the original http.ResponseWriter with negroni.ResponseWriter // and create the gzipResponseWriter. nrw := negroni.NewResponseWriter(w) grw := gzipResponseWriter{ gz, nrw, } // Call the next handler supplying the gzipResponseWriter instead of // the original. next(grw, r) // Delete the content length after we know we have been written to. grw.Header().Del(headerContentLength) }
func (_ Test) GZip() { var in bytes.Buffer w, _ := gzip.NewWriterLevel(&in, gzip.BestSpeed) w.Write(testData) w.Close() out := in.Bytes() e.InfoLog.Println("Result of Gzip compression", len(out)) var in2 bytes.Buffer f, _ := flate.NewWriter(&in2, flate.BestSpeed) f.Write(testData) f.Close() out = in2.Bytes() e.InfoLog.Println("Result of Flate compression", len(out)) }
func Gzip(level int) gin.HandlerFunc { return func(c *gin.Context) { if !shouldCompress(c.Request) { return } gz, err := gzip.NewWriterLevel(c.Writer, level) if err != nil { return } c.Writer.Header().Set("Content-Encoding", "gzip") c.Writer.Header().Set("Vary", "Accept-Encoding") c.Writer = &gzipWriter{c.Writer, gz} defer func() { c.Writer.Header().Set("Content-Length", "") gz.Close() }() c.Next() } }
func acquireGzipWriter(w io.Writer, level int) *gzipWriter { p := gzipWriterPoolMap[level] if p == nil { panic(fmt.Sprintf("BUG: unexpected compression level passed: %d. See compress/gzip for supported levels", level)) } v := p.Get() if v == nil { zw, err := gzip.NewWriterLevel(w, level) if err != nil { panic(fmt.Sprintf("BUG: unexpected error from gzip.NewWriterLevel(%d): %s", level, err)) } return &gzipWriter{ Writer: zw, p: p, } } zw := v.(*gzipWriter) zw.Reset(w) return zw }
func NewWriterLevel(w io.Writer, level int) (*Writer, error) { z, err := gzip.NewWriterLevel(w, level) return (*Writer)(z), err }