Commit 7dbe4228 authored by Matt Holt's avatar Matt Holt

Merge pull request #174 from mholt/gzipfix

gzip: Make it gzip again

Removes mimes filter in favor of extensions filter (might be temporary)
parents cd2b255a b5579ca9
...@@ -28,27 +28,15 @@ func gzipParse(c *Controller) ([]gzip.Config, error) { ...@@ -28,27 +28,15 @@ func gzipParse(c *Controller) ([]gzip.Config, error) {
config := gzip.Config{} config := gzip.Config{}
pathFilter := gzip.PathFilter{make(gzip.Set)} pathFilter := gzip.PathFilter{make(gzip.Set)}
mimeFilter := gzip.MIMEFilter{make(gzip.Set)}
extFilter := gzip.ExtFilter{make(gzip.Set)} extFilter := gzip.ExtFilter{make(gzip.Set)}
// no extra args expected // No extra args expected
if len(c.RemainingArgs()) > 0 { if len(c.RemainingArgs()) > 0 {
return configs, c.ArgErr() return configs, c.ArgErr()
} }
for c.NextBlock() { for c.NextBlock() {
switch c.Val() { switch c.Val() {
case "mimes":
mimes := c.RemainingArgs()
if len(mimes) == 0 {
return configs, c.ArgErr()
}
for _, m := range mimes {
if !gzip.ValidMIME(m) {
return configs, fmt.Errorf("Invalid MIME %v.", m)
}
mimeFilter.Types.Add(m)
}
case "ext": case "ext":
exts := c.RemainingArgs() exts := c.RemainingArgs()
if len(exts) == 0 { if len(exts) == 0 {
...@@ -56,7 +44,7 @@ func gzipParse(c *Controller) ([]gzip.Config, error) { ...@@ -56,7 +44,7 @@ func gzipParse(c *Controller) ([]gzip.Config, error) {
} }
for _, e := range exts { for _, e := range exts {
if !strings.HasPrefix(e, ".") { if !strings.HasPrefix(e, ".") {
return configs, fmt.Errorf(`Invalid extension %v. Should start with "."`, e) return configs, fmt.Errorf(`gzip: invalid extension "%v" (must start with dot)`, e)
} }
extFilter.Exts.Add(e) extFilter.Exts.Add(e)
} }
...@@ -66,14 +54,13 @@ func gzipParse(c *Controller) ([]gzip.Config, error) { ...@@ -66,14 +54,13 @@ func gzipParse(c *Controller) ([]gzip.Config, error) {
return configs, c.ArgErr() return configs, c.ArgErr()
} }
for _, p := range paths { for _, p := range paths {
if p == "/" {
return configs, fmt.Errorf(`gzip: cannot exclude path "/" - remove directive entirely instead`)
}
if !strings.HasPrefix(p, "/") { if !strings.HasPrefix(p, "/") {
return configs, fmt.Errorf(`Invalid path %v. Should start with "/"`, p) return configs, fmt.Errorf(`gzip: invalid path "%v" (must start with /)`, p)
} }
pathFilter.IgnoredPaths.Add(p) pathFilter.IgnoredPaths.Add(p)
// Warn user if / is used
if p == "/" {
fmt.Println("Warning: Paths ignored by gzip includes wildcard(/). No request will be gzipped.\nRemoving gzip directive from Caddyfile is preferred if this is intended.")
}
} }
case "level": case "level":
if !c.NextArg() { if !c.NextArg() {
...@@ -88,22 +75,17 @@ func gzipParse(c *Controller) ([]gzip.Config, error) { ...@@ -88,22 +75,17 @@ func gzipParse(c *Controller) ([]gzip.Config, error) {
config.Filters = []gzip.Filter{} config.Filters = []gzip.Filter{}
// if ignored paths are specified, put in front to filter with path first // If ignored paths are specified, put in front to filter with path first
if len(pathFilter.IgnoredPaths) > 0 { if len(pathFilter.IgnoredPaths) > 0 {
config.Filters = []gzip.Filter{pathFilter} config.Filters = []gzip.Filter{pathFilter}
} }
// if mime types are specified, use it and ignore extensions // Then, if extensions are specified, use those to filter.
if len(mimeFilter.Types) > 0 { // Otherwise, use default extensions filter.
config.Filters = append(config.Filters, mimeFilter) if len(extFilter.Exts) > 0 {
// if extensions are specified, use it
} else if len(extFilter.Exts) > 0 {
config.Filters = append(config.Filters, extFilter) config.Filters = append(config.Filters, extFilter)
// neither is specified, use default mime types
} else { } else {
config.Filters = append(config.Filters, gzip.DefaultMIMEFilter()) config.Filters = append(config.Filters, gzip.DefaultExtFilter())
} }
configs = append(configs, config) configs = append(configs, config)
......
...@@ -59,25 +59,13 @@ func TestGzip(t *testing.T) { ...@@ -59,25 +59,13 @@ func TestGzip(t *testing.T) {
level 3 level 3
} }
`, false}, `, false},
{`gzip { mimes text/html
}`, false},
{`gzip { mimes text/html application/json
}`, false},
{`gzip { mimes text/html application/
}`, true},
{`gzip { mimes text/html /json
}`, true},
{`gzip { mimes /json text/html
}`, true},
{`gzip { not /file {`gzip { not /file
ext .html ext .html
level 1 level 1
mimes text/html text/plain
} }
gzip { not /file1 gzip { not /file1
ext .htm ext .htm
level 3 level 3
mimes text/html text/css
} }
`, false}, `, false},
} }
......
...@@ -3,7 +3,6 @@ package gzip ...@@ -3,7 +3,6 @@ package gzip
import ( import (
"net/http" "net/http"
"path" "path"
"strings"
"github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware"
) )
...@@ -15,6 +14,18 @@ type Filter interface { ...@@ -15,6 +14,18 @@ type Filter interface {
ShouldCompress(*http.Request) bool ShouldCompress(*http.Request) bool
} }
// defaultExtensions is the list of default extensions for which to enable gzipping.
var defaultExtensions = []string{"", ".txt", ".htm", ".html", ".css", ".php", ".js", ".json", ".md", ".xml"}
// DefaultExtFilter creates an ExtFilter with default extensions.
func DefaultExtFilter() ExtFilter {
m := ExtFilter{Exts: make(Set)}
for _, extension := range defaultExtensions {
m.Exts.Add(extension)
}
return m
}
// ExtFilter is Filter for file name extensions. // ExtFilter is Filter for file name extensions.
type ExtFilter struct { type ExtFilter struct {
// Exts is the file name extensions to accept // Exts is the file name extensions to accept
...@@ -47,39 +58,6 @@ func (p PathFilter) ShouldCompress(r *http.Request) bool { ...@@ -47,39 +58,6 @@ func (p PathFilter) ShouldCompress(r *http.Request) bool {
}) })
} }
// MIMEFilter is Filter for request content types.
type MIMEFilter struct {
// Types is the MIME types to accept.
Types Set
}
// defaultMIMETypes is the list of default MIME types to use.
var defaultMIMETypes = []string{
"text/plain", "text/html", "text/css", "application/json", "application/javascript",
"text/x-markdown", "text/xml", "application/xml",
}
// DefaultMIMEFilter creates a MIMEFilter with default types.
func DefaultMIMEFilter() MIMEFilter {
m := MIMEFilter{Types: make(Set)}
for _, mime := range defaultMIMETypes {
m.Types.Add(mime)
}
return m
}
// ShouldCompress checks if the content type of the request
// matches any of the registered ones. It returns true if
// found and false otherwise.
func (m MIMEFilter) ShouldCompress(r *http.Request) bool {
return m.Types.Contains(r.Header.Get("Content-Type"))
}
func ValidMIME(mime string) bool {
s := strings.Split(mime, "/")
return len(s) == 2 && strings.TrimSpace(s[0]) != "" && strings.TrimSpace(s[1]) != ""
}
// Set stores distinct strings. // Set stores distinct strings.
type Set map[string]struct{} type Set map[string]struct{}
......
...@@ -100,32 +100,6 @@ func TestPathFilter(t *testing.T) { ...@@ -100,32 +100,6 @@ func TestPathFilter(t *testing.T) {
} }
} }
func TestMIMEFilter(t *testing.T) {
var filter Filter = DefaultMIMEFilter()
_ = filter.(MIMEFilter)
var mimes = []string{
"text/html", "text/css", "application/json",
}
for i, m := range mimes {
r := urlRequest("file" + m)
r.Header.Set("Content-Type", m)
if !filter.ShouldCompress(r) {
t.Errorf("Test %v: Should be valid filter", i)
}
}
mimes = []string{
"image/jpeg", "image/png",
}
filter = DefaultMIMEFilter()
for i, m := range mimes {
r := urlRequest("file" + m)
r.Header.Set("Content-Type", m)
if filter.ShouldCompress(r) {
t.Errorf("Test %v: Should not be valid filter", i)
}
}
}
func urlRequest(url string) *http.Request { func urlRequest(url string) *http.Request {
r, _ := http.NewRequest("GET", url, nil) r, _ := http.NewRequest("GET", url, nil)
return r return r
......
...@@ -36,8 +36,7 @@ func (g Gzip) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { ...@@ -36,8 +36,7 @@ func (g Gzip) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
outer: outer:
for _, c := range g.Configs { for _, c := range g.Configs {
// Check filters to determine if gzipping is permitted for this // Check filters to determine if gzipping is permitted for this request
// request
for _, filter := range c.Filters { for _, filter := range c.Filters {
if !filter.ShouldCompress(r) { if !filter.ShouldCompress(r) {
continue outer continue outer
......
...@@ -76,46 +76,6 @@ func TestGzipHandler(t *testing.T) { ...@@ -76,46 +76,6 @@ func TestGzipHandler(t *testing.T) {
t.Error(err) t.Error(err)
} }
} }
gz.Configs[0].Filters[1] = DefaultMIMEFilter()
w = httptest.NewRecorder()
gz.Next = nextFunc(true)
var mimes = []string{
"text/html", "text/css", "application/json",
}
for _, m := range mimes {
url := "/file"
r, err := http.NewRequest("GET", url, nil)
if err != nil {
t.Error(err)
}
r.Header.Set("Content-Type", m)
r.Header.Set("Accept-Encoding", "gzip")
_, err = gz.ServeHTTP(w, r)
if err != nil {
t.Error(err)
}
}
w = httptest.NewRecorder()
gz.Next = nextFunc(false)
mimes = []string{
"image/jpeg", "image/png",
}
for _, m := range mimes {
url := "/file"
r, err := http.NewRequest("GET", url, nil)
if err != nil {
t.Error(err)
}
r.Header.Set("Content-Type", m)
r.Header.Set("Accept-Encoding", "gzip")
_, err = gz.ServeHTTP(w, r)
if err != nil {
t.Error(err)
}
}
} }
func nextFunc(shouldGzip bool) middleware.Handler { func nextFunc(shouldGzip bool) middleware.Handler {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment