@marcel91200 / caddy Mirror · read-only / commits / 8b7d6a9e
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

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