Skip to content

Commit 3893906

Browse files
authored
fix(middleware): reject catch-all compress wildcards "/*" and "*/*" (#1156)
NewCompressor(level, "/*") passed validation but stored an empty wildcard key that never matched any Content-Type, silently compressing nothing. Instead of turning it into a compress-everything catch-all, reject both "/*" and "*/*" at construction: compressing every response wastes CPU on already-compressed types (zip, jpeg, png), which is why the middleware keeps a curated default list. Users should pass explicit content types.
1 parent 9b6ddcd commit 3893906

2 files changed

Lines changed: 20 additions & 3 deletions

File tree

‎middleware/compress.go‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ type Compressor struct {
6565
//
6666
// The level should be one of the ones defined in the flate package.
6767
// The types are the content types that are allowed to be compressed.
68+
//
69+
// Catch-all wildcards ("*/*", "/*") are rejected: compressing every response
70+
// wastes CPU on already-compressed types like zip, jpeg or png. Pass explicit
71+
// types instead, e.g. "text/html" or "application/*".
6872
func NewCompressor(level int, types ...string) *Compressor {
6973
// If types are provided, set those as the allowed types. If none are
7074
// provided, use the default list.
@@ -73,9 +77,12 @@ func NewCompressor(level int, types ...string) *Compressor {
7377
if len(types) > 0 {
7478
for _, t := range types {
7579
if strings.Contains(strings.TrimSuffix(t, "/*"), "*") {
76-
panic(fmt.Sprintf("middleware/compress: Unsupported content-type wildcard pattern '%s'. Only '/*' supported", t))
80+
panic(fmt.Sprintf("middleware/compress: Unsupported content-type wildcard pattern '%s'. Only '<type>/*' supported", t))
7781
}
7882
if before, ok := strings.CutSuffix(t, "/*"); ok {
83+
if before == "" {
84+
panic(fmt.Sprintf("middleware/compress: Unsupported content-type wildcard pattern '%s'. Only '<type>/*' supported", t))
85+
}
7986
allowedWildcards[before] = struct{}{}
8087
} else {
8188
allowedTypes[t] = struct{}{}

‎middleware/compress_test.go‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,22 @@ func TestCompressorWildcards(t *testing.T) {
153153
{
154154
name: "invalid wildcard #1",
155155
types: []string{"audio/*wav"},
156-
recover: "middleware/compress: Unsupported content-type wildcard pattern 'audio/*wav'. Only '/*' supported",
156+
recover: "middleware/compress: Unsupported content-type wildcard pattern 'audio/*wav'. Only '<type>/*' supported",
157157
},
158158
{
159159
name: "invalid wildcard #2",
160160
types: []string{"application*/*"},
161-
recover: "middleware/compress: Unsupported content-type wildcard pattern 'application*/*'. Only '/*' supported",
161+
recover: "middleware/compress: Unsupported content-type wildcard pattern 'application*/*'. Only '<type>/*' supported",
162+
},
163+
{
164+
name: "catch-all wildcard #1",
165+
types: []string{"*/*"},
166+
recover: "middleware/compress: Unsupported content-type wildcard pattern '*/*'. Only '<type>/*' supported",
167+
},
168+
{
169+
name: "catch-all wildcard #2",
170+
types: []string{"/*"},
171+
recover: "middleware/compress: Unsupported content-type wildcard pattern '/*'. Only '<type>/*' supported",
162172
},
163173
{
164174
name: "valid wildcard",

0 commit comments

Comments
 (0)