diff --git a/cmd/caddy2/main.go b/cmd/caddy2/main.go index 21b4f572..310b8c1b 100644 --- a/cmd/caddy2/main.go +++ b/cmd/caddy2/main.go @@ -7,6 +7,7 @@ import ( _ "github.com/caddyserver/caddy2/modules/caddyhttp" _ "github.com/caddyserver/caddy2/modules/caddyhttp/caddylog" _ "github.com/caddyserver/caddy2/modules/caddyhttp/encode" + _ "github.com/caddyserver/caddy2/modules/caddyhttp/encode/brotli" _ "github.com/caddyserver/caddy2/modules/caddyhttp/encode/gzip" _ "github.com/caddyserver/caddy2/modules/caddyhttp/encode/zstd" _ "github.com/caddyserver/caddy2/modules/caddyhttp/fileserver" diff --git a/go.mod b/go.mod index 9cb7e4f9..b1cdb2a5 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.12 require ( github.com/DataDog/zstd v1.4.0 // indirect + github.com/andybalholm/brotli v0.0.0-20190430215306-5c318f9037cb // indirect github.com/dustin/go-humanize v1.0.0 github.com/go-acme/lego v2.6.0+incompatible github.com/google/go-cmp v0.3.0 // indirect diff --git a/go.sum b/go.sum index 61016a06..b9d96e19 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/DataDog/zstd v1.4.0 h1:vhoV+DUHnRZdKW1i5UMjAk2G4JY8wN4ayRfYDNdEhwo= github.com/DataDog/zstd v1.4.0/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/andybalholm/brotli v0.0.0-20190430215306-5c318f9037cb h1:Qs8/an94NFS1x2nn7rSI+skKFuw/EGfEYAGS3w/p+jc= +github.com/andybalholm/brotli v0.0.0-20190430215306-5c318f9037cb/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U= github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= @@ -9,6 +11,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= github.com/go-acme/lego v2.6.0+incompatible h1:KxcEWOF5hKtgou4xIqPaXSRF9DoO4OJ90ndwdK6YH/k= github.com/go-acme/lego v2.6.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= +github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw= +github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/klauspost/compress v1.7.1-0.20190613161414-0b31f265a57b h1:LHpBANNM/cw1PAXJtKV9dgfp6ztOKfdGXcltGmqU9aE= diff --git a/modules/caddyhttp/encode/brotli/brotli.go b/modules/caddyhttp/encode/brotli/brotli.go new file mode 100644 index 00000000..3289f0c1 --- /dev/null +++ b/modules/caddyhttp/encode/brotli/brotli.go @@ -0,0 +1,51 @@ +package caddybrotli + +import ( + "fmt" + + "github.com/andybalholm/brotli" + "github.com/caddyserver/caddy2" + "github.com/caddyserver/caddy2/modules/caddyhttp/encode" +) + +func init() { + caddy2.RegisterModule(caddy2.Module{ + Name: "http.encoders.brotli", + New: func() interface{} { return new(Brotli) }, + }) +} + +// Brotli can create brotli encoders. Note that brotli +// is not known for great encoding performance. +type Brotli struct { + Quality *int `json:"quality,omitempty"` +} + +// Validate validates b's configuration. +func (b Brotli) Validate() error { + if b.Quality != nil { + quality := *b.Quality + if quality < brotli.BestSpeed { + return fmt.Errorf("quality too low; must be >= %d", brotli.BestSpeed) + } + if quality > brotli.BestCompression { + return fmt.Errorf("quality too high; must be <= %d", brotli.BestCompression) + } + } + return nil +} + +// NewEncoder returns a new brotli writer. +func (b Brotli) NewEncoder() encode.Encoder { + quality := brotli.DefaultCompression + if b.Quality != nil { + quality = *b.Quality + } + return brotli.NewWriterLevel(nil, quality) +} + +// Interface guards +var ( + _ encode.Encoding = (*Brotli)(nil) + _ caddy2.Validator = (*Brotli)(nil) +) diff --git a/modules/caddyhttp/encode/gzip/gzip.go b/modules/caddyhttp/encode/gzip/gzip.go index 0da5fc34..b08385ab 100644 --- a/modules/caddyhttp/encode/gzip/gzip.go +++ b/modules/caddyhttp/encode/gzip/gzip.go @@ -3,6 +3,7 @@ package caddygzip import ( "compress/flate" "compress/gzip" // TODO: consider using https://github.com/klauspost/compress/gzip + "fmt" "github.com/caddyserver/caddy2" "github.com/caddyserver/caddy2/modules/caddyhttp/encode" @@ -20,17 +21,37 @@ type Gzip struct { Level int `json:"level,omitempty"` } -// NewEncoder returns a new gzip writer. -func (g Gzip) NewEncoder() encode.Encoder { - if g.Level <= flate.NoCompression { +// Provision provisions g's configuration. +func (g *Gzip) Provision(ctx caddy2.Context) error { + if g.Level == 0 { g.Level = defaultGzipLevel } - if g.Level > flate.BestCompression { - g.Level = flate.BestCompression + return nil +} + +// Validate validates g's configuration. +func (g Gzip) Validate() error { + if g.Level < flate.NoCompression { + return fmt.Errorf("quality too low; must be >= %d", flate.NoCompression) } + if g.Level > flate.BestCompression { + return fmt.Errorf("quality too high; must be <= %d", flate.BestCompression) + } + return nil +} + +// NewEncoder returns a new gzip writer. +func (g Gzip) NewEncoder() encode.Encoder { writer, _ := gzip.NewWriterLevel(nil, g.Level) return writer } // Informed from http://blog.klauspost.com/gzip-performance-for-go-webservers/ var defaultGzipLevel = 5 + +// Interface guards +var ( + _ encode.Encoding = (*Gzip)(nil) + _ caddy2.Provisioner = (*Gzip)(nil) + _ caddy2.Validator = (*Gzip)(nil) +) diff --git a/modules/caddyhttp/encode/zstd/zstd.go b/modules/caddyhttp/encode/zstd/zstd.go index 6afe53ef..eb66ad87 100644 --- a/modules/caddyhttp/encode/zstd/zstd.go +++ b/modules/caddyhttp/encode/zstd/zstd.go @@ -1,4 +1,4 @@ -package caddystd +package caddyzstd import ( "github.com/caddyserver/caddy2" @@ -21,3 +21,6 @@ func (z Zstd) NewEncoder() encode.Encoder { writer, _ := zstd.NewWriter(nil) return writer } + +// Interface guard +var _ encode.Encoding = (*Zstd)(nil)