summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/labstack/echo/middleware/compress.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/labstack/echo/middleware/compress.go')
-rw-r--r--vendor/github.com/labstack/echo/middleware/compress.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/vendor/github.com/labstack/echo/middleware/compress.go b/vendor/github.com/labstack/echo/middleware/compress.go
new file mode 100644
index 00000000..eee67b37
--- /dev/null
+++ b/vendor/github.com/labstack/echo/middleware/compress.go
@@ -0,0 +1,121 @@
+package middleware
+
+import (
+ "bufio"
+ "compress/gzip"
+ "io"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "strings"
+
+ "github.com/labstack/echo"
+)
+
+type (
+ // GzipConfig defines the config for Gzip middleware.
+ GzipConfig struct {
+ // Skipper defines a function to skip middleware.
+ Skipper Skipper
+
+ // Gzip compression level.
+ // Optional. Default value -1.
+ Level int `json:"level"`
+ }
+
+ gzipResponseWriter struct {
+ io.Writer
+ http.ResponseWriter
+ }
+)
+
+const (
+ gzipScheme = "gzip"
+)
+
+var (
+ // DefaultGzipConfig is the default Gzip middleware config.
+ DefaultGzipConfig = GzipConfig{
+ Skipper: DefaultSkipper,
+ Level: -1,
+ }
+)
+
+// Gzip returns a middleware which compresses HTTP response using gzip compression
+// scheme.
+func Gzip() echo.MiddlewareFunc {
+ return GzipWithConfig(DefaultGzipConfig)
+}
+
+// GzipWithConfig return Gzip middleware with config.
+// See: `Gzip()`.
+func GzipWithConfig(config GzipConfig) echo.MiddlewareFunc {
+ // Defaults
+ if config.Skipper == nil {
+ config.Skipper = DefaultGzipConfig.Skipper
+ }
+ if config.Level == 0 {
+ config.Level = DefaultGzipConfig.Level
+ }
+
+ return func(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ if config.Skipper(c) {
+ return next(c)
+ }
+
+ res := c.Response()
+ res.Header().Add(echo.HeaderVary, echo.HeaderAcceptEncoding)
+ if strings.Contains(c.Request().Header.Get(echo.HeaderAcceptEncoding), gzipScheme) {
+ res.Header().Add(echo.HeaderContentEncoding, gzipScheme) // Issue #806
+ rw := res.Writer
+ w, err := gzip.NewWriterLevel(rw, config.Level)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if res.Size == 0 {
+ if res.Header().Get(echo.HeaderContentEncoding) == gzipScheme {
+ res.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.
+ res.Writer = rw
+ w.Reset(ioutil.Discard)
+ }
+ w.Close()
+ }()
+ grw := &gzipResponseWriter{Writer: w, ResponseWriter: rw}
+ res.Writer = grw
+ }
+ return next(c)
+ }
+ }
+}
+
+func (w *gzipResponseWriter) WriteHeader(code int) {
+ if code == http.StatusNoContent { // Issue #489
+ w.ResponseWriter.Header().Del(echo.HeaderContentEncoding)
+ }
+ w.ResponseWriter.WriteHeader(code)
+}
+
+func (w *gzipResponseWriter) Write(b []byte) (int, error) {
+ if w.Header().Get(echo.HeaderContentType) == "" {
+ w.Header().Set(echo.HeaderContentType, http.DetectContentType(b))
+ }
+ return w.Writer.Write(b)
+}
+
+func (w *gzipResponseWriter) Flush() error {
+ return w.Writer.(*gzip.Writer).Flush()
+}
+
+func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ return w.ResponseWriter.(http.Hijacker).Hijack()
+}
+
+func (w *gzipResponseWriter) CloseNotify() <-chan bool {
+ return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}