// 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).
518308
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))

		// Check if render middleware has been registered,
		// if yes, we need to modify ResponseWriter for it as well.
		if _, ok := ctx.Render.(*macaron.DummyRender); !ok {
			ctx.Render.SetResponseWriter(gzw)
		}

		ctx.Next()

		// delete content length after we know we have been written to
		gzw.Header().Del("Content-Length")
	}
}
1023020
func RegisterDecompressor(a CompressionAlgorithm, d Decompressor) {
	if decompressors[a] != nil {
		log.Printf("RegisterCompressor: overwriting current decompressor for %s\n", a)
	}
	decompressors[a] = d
}
292026
func NewGzipResponseWriter(writer http.ResponseWriter, compressionLevel int) gzipResponseWriter {
	gzWriter, _ := gzip.NewWriterLevel(writer, compressionLevel)
	return gzipResponseWriter{ResponseWriter: writer, gzWriter: gzWriter}
}
90948
func Gzip(next http.HandlerFunc) http.HandlerFunc {

	return func(w http.ResponseWriter, r *http.Request) {

		w.Header().Add(pure.Vary, pure.AcceptEncoding)

		if strings.Contains(r.Header.Get(pure.AcceptEncoding), pure.Gzip) {

			gz := gzipPool.Get().(*gzipWriter)
			gz.sniffComplete = false
			gzr := gz.Writer.(*gzip.Writer)
			gzr.Reset(w)
			gz.ResponseWriter = w

			w.Header().Set(pure.ContentEncoding, pure.Gzip)

			w = gz
			defer func() {

				if !gz.sniffComplete {
					// We have to reset response to it's pristine state when
					// nothing is written to body.
					w.Header().Del(pure.ContentEncoding)
					gzr.Reset(ioutil.Discard)
				}

				gzr.Close()
				gzipPool.Put(gz)
			}()
		}

		next(w, r)
	}
}
1359498
func NewGzip() *Gzip {
	gz := new(Gzip)
	gz.Options = new(Options)
	return gz
}
886018
func (w *GzipResponseWriter) FlushResponse() {
	w.WriteNow(w.chunks)
	w.ResponseWriter.FlushResponse()
}
1288826
func NewGZIPCompressorWithLevel(level int) (Compressor, error) {
	if level < gzip.DefaultCompression || level > gzip.BestCompression {
		return nil, fmt.Errorf("grpc: invalid compression level: %d", level)
	}
	return &gzipCompressor{
		pool: sync.Pool{
			New: func() interface{} {
				w, err := gzip.NewWriterLevel(ioutil.Discard, level)
				if err != nil {
					panic(err)
				}
				return w
			},
		},
	}, nil
}
1033876
func (r *ResponseFilterWriter) WriteHeader(code int) {
	// Determine if compression should be used or not.
	r.shouldCompress = true
	for _, filter := range r.filters {
		if !filter.ShouldCompress(r) {
			r.shouldCompress = false
			break
		}
	}

	if r.shouldCompress {
		// replace discard writer with ResponseWriter
		if gzWriter, ok := r.gzipResponseWriter.Writer().(*gzip.Writer); ok {
			gzWriter.Reset(r.ResponseWriter)
		}
		// use gzip WriteHeader to include and delete
		// necessary headers
		r.gzipResponseWriter.WriteHeader(code)
	} else {
		r.ResponseWriter.WriteHeader(code)
	}
	r.statusCodeWritten = true
}
1202930
func GZip(h http.Handler) http.Handler {
	hfunc := func(w http.ResponseWriter, r *http.Request) {
		ae := strings.Split(r.Header.Get("Accept-Encoding"), ",")
		acceptsGzip := false
		for i := range ae {
			if strings.TrimSpace(ae[i]) == "gzip" {
				acceptsGzip = true
				break
			}
		}
		if acceptsGzip {
			// Remove "Accept-Encoding" header to ensure applications further
			// down the line don't attempt to gzip the response again.
			r.Header.Del("Accept-Encoding")
			gzw := gzip.NewWriter(w)
			wrapper := &gzipWrapper{w, gzw, &sync.Mutex{}, true, false}
			hijacker, ok := w.(http.Hijacker)
			if ok {
				// if writer accepts hijacking pass a hijackable wrapper
				hijackableWrapper := &gzipHijacker{wrapper, hijacker, false}
				defer func() {
					if !hijackableWrapper.hijacked {
						gzw.Close()
					}
				}()
				w = hijackableWrapper
			} else {
				defer gzw.Close()
				w = wrapper
			}
		}
		h.ServeHTTP(w, r)
	}
	return http.HandlerFunc(hfunc)
}
795459
func (grw *gzipResponseWriter) Write(b []byte) (int, error) {
	if len(grw.Header().Get(headerContentType)) == 0 {
		grw.Header().Set(headerContentType, http.DetectContentType(b))
	}

	// If we already decided to gzip, do that.
	if grw.gzw != nil {
		return grw.gzw.Write(b)
	}

	// If we have already decided not to gzip, do that.
	if grw.shouldCompress != nil && !*grw.shouldCompress {
		return grw.ResponseWriter.Write(b)
	}

	// Detect types, check status code.
	if grw.shouldCompress == nil {
		s := grw.o.shouldCompress(grw.Header().Get(headerContentType), grw.statusCode)
		grw.shouldCompress = &s
		if !s {
			grw.ResponseWriter.WriteHeader(grw.statusCode)
			return grw.ResponseWriter.Write(b)
		}
	}

	// Check if length is above minimum,
	// if not save to buffer.
	size := len(b) + grw.buf.Len()
	if size < grw.o.minSize {
		return grw.buf.Write(b)
	}

	// Reset our gzip writer to use the http.ResponseWriter
	// Retrieve gzip writer from the pool. Reset it to use the ResponseWriter.
	// This allows us to re-use an already allocated buffer rather than
	// allocating a new buffer for every request.
	gz := grw.pool.Get().(*gzip.Writer)

	// We must write header now
	grw.Header().Set(headerContentEncoding, encodingGzip)
	grw.Header().Set(headerVary, headerAcceptEncoding)
	grw.Header().Del(headerContentLength)
	grw.Header().Del(headerAcceptRanges)
	grw.ResponseWriter.WriteHeader(grw.statusCode)
	gz.Reset(grw.ResponseWriter)
	grw.gzw = gz

	// Write buffer
	if grw.buf.Len() > 0 {
		_, err := gz.Write(grw.buf.Bytes())
		if err != nil {
			return 0, err
		}
		grw.buf.Reset()
	}
	return gz.Write(b)
}
412910
func (g *Gzip) Decode(r io.Reader, w io.Writer) error {
	gzr, err := gzip.NewReader(r)
	if err != nil {
		return err
	}
	defer gzr.Close()
	_, err = io.Copy(w, gzr)
	return err
}
921096
func GzipHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") || w.Header().Get("Content-Encoding") != "" || w.Header().Get("Vary") != "" {
			h.ServeHTTP(w, r)
			return
		}
		w.Header().Set("Content-Encoding", "gzip")
		w.Header().Set("Vary", "Accept-Encoding")
		gz := gzip.NewWriter(w)
		defer gz.Close()
		h.ServeHTTP(&gzipResponseWriter{
			Writer:         gz,
			ResponseWriter: w,
		}, r)
	})
}
613391
func NewGzipCompressionLevel(level int) Compression {
	return &genericCompression{
		wf: func(w io.Writer) (io.WriteCloser, error) { return gzip.NewWriterLevel(w, level) },
		rf: func(r io.Reader) (io.ReadCloser, error) { return gzip.NewReader(r) },
	}
}
873847
func wantsCompressedResponse(httpRequest *http.Request) (bool, string) {
	header := httpRequest.Header.Get(HEADER_AcceptEncoding)
	gi := strings.Index(header, ENCODING_GZIP)
	zi := strings.Index(header, ENCODING_DEFLATE)
	// use in order of appearance
	if gi == -1 {
		return zi != -1, ENCODING_DEFLATE
	} else if zi == -1 {
		return gi != -1, ENCODING_GZIP
	} else {
		if gi < zi {
			return true, ENCODING_GZIP
		}
		return true, ENCODING_DEFLATE
	}
}
1000434
func getGzipWriter(w http.ResponseWriter) (*gzipResponseWriter, bool) {
	gz, ok := GetResponseWriter(w, func(tst http.ResponseWriter) bool {
		_, ok := tst.(*gzipResponseWriter)
		return ok
	})
	if ok {
		return gz.(*gzipResponseWriter), true
	}
	return nil, false
}
823165
func (z *ReadZipper) GzipHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var err error
		if "gzip" == r.Header.Get("Content-Encoding") {
			gzi := z.zippers.Get()
			if gzi != nil {
				gz := gzi.(*gzip.Reader)
				// put it back
				defer z.zippers.Put(gz)
				err = gz.Reset(r.Body)
				if err == nil {
					defer log.IfErr(z.Log, gz.Close())
					// nasty? could construct another object but seems expensive
					r.Body = gz
					atomic.AddInt64(&z.HitCount, 1)
					h.ServeHTTP(w, r)
					return
				}
			}
		}
		if err != nil {
			atomic.AddInt64(&z.ErrCount, 1)
			w.WriteHeader(http.StatusBadRequest)
			_, err := w.Write([]byte("error handling gzip compressed request " + err.Error()))
			log.IfErr(z.Log, err)
			return
		}
		atomic.AddInt64(&z.MissCount, 1)
		h.ServeHTTP(w, r)
	})
}
1015920
func (w *GzipResponseWriter) BeginGzipResponse(underline ResponseWriter) {
	w.ResponseWriter = underline

	w.chunks = w.chunks[0:0]
	w.disabled = false
}