@marcel91200 / caddy Mirror · read-only / commits / 0fc97211
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

http: Make path matcher case-insensitive

Adds tests for both the path matcher and host matcher for case insensitivity. If case sensitivity is required for the path, a regexp matcher can be used instead. This is the v2 equivalent fix of PR #2882.

Matthew Holt committed Nov 15, 2019 at 12:47 UTC 0fc97211abd46098f5953fc6b152aa891060fca5
2 files changed +45 -6
modules/caddyhttp/matchers.go
+14 -5
@@ -33,10 +33,10 @@ import (
33 )
34
35 type (
36 - // MatchHost matches requests by the Host value.
36 + // MatchHost matches requests by the Host value (case-insensitive).
37 MatchHost []string
38
39 - // MatchPath matches requests by the URI's path.
39 + // MatchPath matches requests by the URI's path (case-insensitive).
40 MatchPath []string
41
42 // MatchPathRE matches requests by a regular expression on the URI's path.
@@ -154,20 +154,29 @@ func (MatchPath) CaddyModule() caddy.ModuleInfo {
154 }
155 }
156
157 +// Provision lower-cases the paths in m to ensure case-insensitive matching.
158 +func (m MatchPath) Provision(_ caddy.Context) error {
159 + for i := range m {
160 + m[i] = strings.ToLower(m[i])
161 + }
162 + return nil
163 +}
164 +
165 // Match returns true if r matches m.
166 func (m MatchPath) Match(r *http.Request) bool {
167 + lowerPath := strings.ToLower(r.URL.Path)
168 for _, matchPath := range m {
169 // as a special case, if the first character is a
170 // wildcard, treat it as a quick suffix match
171 if strings.HasPrefix(matchPath, "*") {
163 - return strings.HasSuffix(r.URL.Path, matchPath[1:])
172 + return strings.HasSuffix(lowerPath, matchPath[1:])
173 }
174 // can ignore error here because we can't handle it anyway
166 - matches, _ := filepath.Match(matchPath, r.URL.Path)
175 + matches, _ := filepath.Match(matchPath, lowerPath)
176 if matches {
177 return true
178 }
170 - if strings.HasPrefix(r.URL.Path, matchPath) {
179 + if strings.HasPrefix(lowerPath, matchPath) {
180 return true
181 }
182 }
modules/caddyhttp/matchers_test.go
+31 -1
@@ -47,6 +47,16 @@ func TestHostMatcher(t *testing.T) {
47 input: "example.com",
48 expect: true,
49 },
50 + {
51 + match: MatchHost{"EXAMPLE.COM"},
52 + input: "example.com",
53 + expect: true,
54 + },
55 + {
56 + match: MatchHost{"example.com"},
57 + input: "EXAMPLE.COM",
58 + expect: true,
59 + },
60 {
61 match: MatchHost{"example.com"},
62 input: "foo.example.com",
@@ -72,6 +82,11 @@ func TestHostMatcher(t *testing.T) {
82 input: "example.com",
83 expect: false,
84 },
85 + {
86 + match: MatchHost{"*.example.com"},
87 + input: "SUB.EXAMPLE.COM",
88 + expect: true,
89 + },
90 {
91 match: MatchHost{"*.example.com"},
92 input: "foo.example.com",
@@ -174,7 +189,12 @@ func TestPathMatcher(t *testing.T) {
189 },
190 {
191 match: MatchPath{"*.ext"},
177 - input: "foo.ext",
192 + input: "/foo.ext",
193 + expect: true,
194 + },
195 + {
196 + match: MatchPath{"*.php"},
197 + input: "/index.PHP",
198 expect: true,
199 },
200 {
@@ -192,6 +212,16 @@ func TestPathMatcher(t *testing.T) {
212 input: "/foo/bar/bam",
213 expect: false,
214 },
215 + {
216 + match: MatchPath{"/foo"},
217 + input: "/FOO",
218 + expect: true,
219 + },
220 + {
221 + match: MatchPath{"/foo/bar.txt"},
222 + input: "/foo/BAR.txt",
223 + expect: true,
224 + },
225 } {
226 req := &http.Request{URL: &url.URL{Path: tc.input}}
227 actual := tc.match.Match(req)