// GzipWithConfig return Gzip middleware with config.
// See: `Gzip()`.
177652
func GzipWithConfig(config *GzipConfig) echo.MiddlewareFunc {
	// Defaults
	if config.Skipper == nil {
		config.Skipper = DefaultGzipConfig.Skipper
	}
	if config.Level == 0 {
		config.Level = DefaultGzipConfig.Level
	}
	scheme := `gzip`

	return func(h echo.Handler) echo.Handler {
		return echo.HandlerFunc(func(c echo.Context) error {
			if config.Skipper(c) {
				return h.Handle(c)
			}
			resp := c.Response()
			resp.Header().Add(echo.HeaderVary, echo.HeaderAcceptEncoding)
			if strings.Contains(c.Request().Header().Get(echo.HeaderAcceptEncoding), scheme) {
				resp.Header().Add(echo.HeaderContentEncoding, scheme)
				rw := resp.Writer()
				w, err := gzip.NewWriterLevel(rw, config.Level)
				if err != nil {
					return err
				}
				defer func() {
					if resp.Size() == 0 {
						if resp.Header().Get(echo.HeaderContentEncoding) == scheme {
							resp.Header().Del(echo.HeaderContentEncoding)
						}
						// We have to reset response to it's pristine state when
						// nothing is written to body or error is returned.
						// See issue #424, #407.
						resp.SetWriter(rw)
						w.Reset(ioutil.Discard)
					}
					w.Close()
				}()
				resp.SetWriter(&gzipWriter{Writer: w, Response: resp})
			}
			return h.Handle(c)
		})
	}
}
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)
	})
}
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) },
	}
}
150238
func GzipMW(level int) alice.Constructor {
	return func(next http.Handler) http.Handler {
		return Gzip(level, next)
	}
}
627204
func (h *HTTPBin) Gzip(w http.ResponseWriter, r *http.Request) {
	resp := &gzipResponse{
		Headers: getRequestHeaders(r),
		Origin:  getOrigin(r),
		Gzipped: true,
	}
	body, _ := json.Marshal(resp)

	buf := &bytes.Buffer{}
	gzw := gzip.NewWriter(buf)
	gzw.Write(body)
	gzw.Close()

	gzBody := buf.Bytes()

	w.Header().Set("Content-Encoding", "gzip")
	writeJSON(w, gzBody, http.StatusOK)
}
1318271
func loadConfig(configName string) (map[string]string, error) {
	klog.V(4).Info(log("loading config file %s", configName))
	file, err := os.Open(configName)
	if err != nil {
		klog.Error(log("failed to open config file %s: %v", configName, err))
		return nil, err
	}
	defer file.Close()
	data := map[string]string{}
	if err := gob.NewDecoder(file).Decode(&data); err != nil {
		klog.Error(log("failed to parse config data %s: %v", configName, err))
		return nil, err
	}
	applyConfigDefaults(data)
	if err := validateConfigs(data); err != nil {
		klog.Error(log("failed to load ConfigMap %s: %v", err))
		return nil, err
	}

	return data, nil
}
904626
func (p *GzipPool) WriteGzip(w io.Writer, b []byte) (int, error) {
	gzipWriter := p.AcquireGzipWriter(w)
	n, err := gzipWriter.Write(b)
	p.ReleaseGzipWriter(gzipWriter)
	return n, err
}
785063
func (w *gzipResponseWriter) WriteHeader(code int) {
	w.Header().Del("Content-Length")
	w.Header().Set("Content-Encoding", "gzip")
	w.Header().Add("Vary", "Accept-Encoding")
	originalEtag := w.Header().Get("ETag")
	if originalEtag != "" && !strings.HasPrefix(originalEtag, "W/") {
		w.Header().Set("ETag", "W/"+originalEtag)
	}
	w.ResponseWriterWrapper.WriteHeader(code)
	w.statusCodeWritten = true
}
713168
func Gzip(level int, next http.Handler) http.Handler {
	return &handler{
		compressionLevel: level,
		next:             next,
	}
}
1106522
func Compress(config CompressConfig) Middleware {
	// fill default config
	if config.Skipper == nil {
		config.Skipper = DefaultSkipper
	}

	mapTypes := make(map[string]struct{})
	for _, t := range strings.Split(config.Types, " ") {
		mapTypes[t] = struct{}{}
	}

	pool := &sync.Pool{
		New: func() interface{} {
			return config.New()
		},
	}

	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if config.Skipper(r) {
				h.ServeHTTP(w, r)
				return
			}

			// skip if client not support
			if !strings.Contains(r.Header.Get("Accept-Encoding"), config.Encoding) {
				h.ServeHTTP(w, r)
				return
			}

			// skip if web socket
			if r.Header.Get("Sec-WebSocket-Key") != "" {
				h.ServeHTTP(w, r)
				return
			}

			hh := w.Header()

			// skip if already encode
			if hh.Get("Content-Encoding") != "" {
				h.ServeHTTP(w, r)
				return
			}

			if config.Vary {
				addHeaderIfNotExists(hh, "Vary", "Accept-Encoding")
			}

			gw := &compressWriter{
				ResponseWriter: w,
				pool:           pool,
				encoding:       config.Encoding,
				types:          mapTypes,
				minLength:      config.MinLength,
			}
			defer gw.Close()

			h.ServeHTTP(gw, r)
		})
	}
}
954336
func (ctx *context) TryWriteGzip(b []byte) (int, error) {
	n, err := ctx.WriteGzip(b)
	if err != nil {
		// check if the error came from gzip not allowed and not the writer itself
		if _, ok := err.(*errors.Error); ok {
			// client didn't supported gzip, write them uncompressed:
			return ctx.writer.Write(b)
		}
	}
	return n, err
}
708829
func Gzip(config ...*GzipConfig) echo.MiddlewareFunc {
	if len(config) < 1 || config[0] == nil {
		return GzipWithConfig(DefaultGzipConfig)
	}
	return GzipWithConfig(config[0])
}
792919
func (z *Writer) writeString(s string) (err error) {
	// GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.
	needconv := false
	for _, v := range s {
		if v == 0 || v > 0xff {
			return errors.New("gzip.Write: non-Latin-1 header string")
		}
		if v > 0x7f {
			needconv = true
		}
	}
	if needconv {
		b := make([]byte, 0, len(s))
		for _, v := range s {
			b = append(b, byte(v))
		}
		_, err = z.w.Write(b)
	} else {
		_, err = io.WriteString(z.w, s)
	}
	if err != nil {
		return err
	}
	// GZIP strings are NUL-terminated.
	z.buf[0] = 0
	_, err = z.w.Write(z.buf[:1])
	return err
}
305254
func GZIPHandler(w http.ResponseWriter, r *http.Request) {
	h, _, _ := net.SplitHostPort(r.RemoteAddr)

	v := gzipResponse{
		headersResponse: headersResponse{getHeaders(r)},
		ipResponse:      ipResponse{h},
		Gzipped:         true,
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Add("Content-Encoding", "gzip")
	ww := gzip.NewWriter(w)
	defer ww.Close() // flush
	if err := writeJSON(ww, v); err != nil {
		writeErrorJSON(w, errors.Wrap(err, "failed to write json"))
	}
}
1365020
func (g Gzip) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
		return g.Next.ServeHTTP(w, r)
	}
outer:
	for _, c := range g.Configs {

		// Check request filters to determine if gzipping is permitted for this request
		for _, filter := range c.RequestFilters {
			if !filter.ShouldCompress(r) {
				continue outer
			}
		}

		// In order to avoid unused memory allocation, gzip.putWriter only be called when gzip compression happened.
		// see https://github.com/mholt/caddy/issues/2395
		gz := &gzipResponseWriter{
			ResponseWriterWrapper: &httpserver.ResponseWriterWrapper{ResponseWriter: w},
			newWriter: func() io.Writer {
				// gzipWriter modifies underlying writer at init,
				// use a discard writer instead to leave ResponseWriter in
				// original form.
				return getWriter(c.Level)
			},
		}

		defer func() {
			if gzWriter, ok := gz.internalWriter.(*gzip.Writer); ok {
				putWriter(c.Level, gzWriter)
			}
		}()

		var rw http.ResponseWriter
		// if no response filter is used
		if len(c.ResponseFilters) == 0 {
			// replace discard writer with ResponseWriter
			if gzWriter, ok := gz.Writer().(*gzip.Writer); ok {
				gzWriter.Reset(w)
			}
			rw = gz
		} else {
			// wrap gzip writer with ResponseFilterWriter
			rw = NewResponseFilterWriter(c.ResponseFilters, gz)
		}

		// Any response in forward middleware will now be compressed
		status, err := g.Next.ServeHTTP(rw, r)

		// If there was an error that remained unhandled, we need
		// to send something back before gzipWriter gets closed at
		// the return of this method!
		if status >= 400 {
			httpserver.DefaultErrorFunc(w, r, status)
			return 0, err
		}
		return status, err
	}

	// no matching filter
	return g.Next.ServeHTTP(w, r)
}
65202
func (c *Cache) Config() Config {
	c.Lock()
	defer c.Unlock()
	return c.config
}
781242
func NewZip(dest io.Writer) *Zip {
	writer := zip.NewWriter(dest)

	writer.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
		return flate.NewWriter(out, flate.DefaultCompression)
	})

	return &Zip{writer: writer}
}