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
v2: fixes query matcher parsing (#2901)
* fixes query matcher parsing * return correct argument error when parsing query matcher
Mark Sargent committed
Nov 30, 2019 at 09:05 UTC
8b7d6a9ee8b7f62142df3516a9d9b96031be33fd
3 files changed
+137
-5
caddyconfig/httpcaddyfile/parser_test.go
new
+66
@@ -0,0 +1,66 @@
1
+// Copyright 2015 Matthew Holt and The Caddy Authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+// http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package httpcaddyfile
16
+
17
+import (
18
+ "testing"
19
+
20
+ caddyfile "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
21
+)
22
+
23
+func TestParse(t *testing.T) {
24
+
25
+ for i, tc := range []struct {
26
+ input string
27
+ expectWarn bool
28
+ expectError bool
29
+ }{
30
+ {
31
+ input: `http://localhost
32
+ matcher debug {
33
+ query showdebug=1
34
+ }
35
+ `,
36
+ expectWarn: false,
37
+ expectError: false,
38
+ },
39
+ {
40
+ input: `http://localhost
41
+ matcher debug {
42
+ query bad format
43
+ }
44
+ `,
45
+ expectWarn: false,
46
+ expectError: true,
47
+ },
48
+ } {
49
+
50
+ adapter := caddyfile.Adapter{
51
+ ServerType: ServerType{},
52
+ }
53
+
54
+ _, warnings, err := adapter.Adapt([]byte(tc.input), nil)
55
+
56
+ if len(warnings) > 0 != tc.expectWarn {
57
+ t.Errorf("Test %d warning expectation failed Expected: %v, got %v", i, tc.expectWarn, warnings)
58
+ continue
59
+ }
60
+
61
+ if err != nil != tc.expectError {
62
+ t.Errorf("Test %d error expectation failed Expected: %v, got %s", i, tc.expectError, err)
63
+ continue
64
+ }
65
+ }
66
+}
modules/caddyhttp/matchers.go
+15
-5
@@ -255,8 +255,16 @@ func (MatchQuery) CaddyModule() caddy.ModuleInfo {
255
256
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
257
func (m *MatchQuery) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
258
+ if *m == nil {
259
+ *m = make(map[string][]string)
260
+ }
261
+
262
for d.Next() {
259
- parts := strings.SplitN(d.Val(), "=", 2)
263
+ var query string
264
+ if !d.Args(&query) {
265
+ return d.ArgErr()
266
+ }
267
+ parts := strings.SplitN(query, "=", 2)
268
if len(parts) != 2 {
269
return d.Errf("malformed query matcher token: %s; must be in param=val format", d.Val())
270
}
@@ -268,10 +276,12 @@ func (m *MatchQuery) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
276
// Match returns true if r matches m.
277
func (m MatchQuery) Match(r *http.Request) bool {
278
for param, vals := range m {
271
- paramVal := r.URL.Query().Get(param)
272
- for _, v := range vals {
273
- if paramVal == v {
274
- return true
279
+ paramVal, found := r.URL.Query()[param]
280
+ if found {
281
+ for _, v := range vals {
282
+ if paramVal[0] == v || v == "*" {
283
+ return true
284
+ }
285
}
286
}
287
}
modules/caddyhttp/matchers_test.go
+56
@@ -391,6 +391,62 @@ func TestHeaderMatcher(t *testing.T) {
391
}
392
}
393
394
+func TestQueryMatcher(t *testing.T) {
395
+ for i, tc := range []struct {
396
+ scenario string
397
+ match MatchQuery
398
+ input string
399
+ expect bool
400
+ }{
401
+ {
402
+ scenario: "non match against a specific value",
403
+ match: MatchQuery{"debug": []string{"1"}},
404
+ input: "/",
405
+ expect: false,
406
+ },
407
+ {
408
+ scenario: "match against a specific value",
409
+ match: MatchQuery{"debug": []string{"1"}},
410
+ input: "/?debug=1",
411
+ expect: true,
412
+ },
413
+ {
414
+ scenario: "match against a wildcard",
415
+ match: MatchQuery{"debug": []string{"*"}},
416
+ input: "/?debug=something",
417
+ expect: true,
418
+ },
419
+ {
420
+ scenario: "non match against a wildcarded",
421
+ match: MatchQuery{"debug": []string{"*"}},
422
+ input: "/?other=something",
423
+ expect: false,
424
+ },
425
+ {
426
+ scenario: "match against an empty value",
427
+ match: MatchQuery{"debug": []string{""}},
428
+ input: "/?debug",
429
+ expect: true,
430
+ },
431
+ {
432
+ scenario: "non match against an empty value",
433
+ match: MatchQuery{"debug": []string{""}},
434
+ input: "/?someparam",
435
+ expect: false,
436
+ },
437
+ } {
438
+
439
+ u, _ := url.Parse(tc.input)
440
+
441
+ req := &http.Request{URL: u}
442
+ actual := tc.match.Match(req)
443
+ if actual != tc.expect {
444
+ t.Errorf("Test %d %v: Expected %t, got %t for '%s'", i, tc.match, tc.expect, actual, tc.input)
445
+ continue
446
+ }
447
+ }
448
+}
449
+
450
func TestHeaderREMatcher(t *testing.T) {
451
for i, tc := range []struct {
452
match MatchHeaderRE