Compare commits

..

3 Commits

Author SHA1 Message Date
Matthew Holt 7ce5c0aaac caddyhttp: Reject conflicting values in query strings 2022-10-24 11:07:29 -06:00
BakaFT a999b70727 cmd: Add missing \n to HelpTemplate (#5151) 2022-10-17 11:51:41 +03:00
Francis Lavoie 1cd594963e docs: Fix templates documentation, stray newline breaks godoc (#5149) 2022-10-16 12:25:44 -04:00
4 changed files with 44 additions and 10 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ const fullDocsFooter = `Full documentation is available at:
https://caddyserver.com/docs/command-line` https://caddyserver.com/docs/command-line`
func init() { func init() {
rootCmd.SetHelpTemplate(rootCmd.HelpTemplate() + "\n" + fullDocsFooter) rootCmd.SetHelpTemplate(rootCmd.HelpTemplate() + "\n" + fullDocsFooter + "\n")
} }
func caddyCmdToCoral(caddyCmd Command) *cobra.Command { func caddyCmdToCoral(caddyCmd Command) *cobra.Command {
+17 -6
View File
@@ -123,6 +123,7 @@ type (
// keyed by the query keys, with an array of string values to match for that key. // keyed by the query keys, with an array of string values to match for that key.
// Query key matches are exact, but wildcards may be used for value matches. Both // Query key matches are exact, but wildcards may be used for value matches. Both
// keys and values may be placeholders. // keys and values may be placeholders.
//
// An example of the structure to match `?key=value&topic=api&query=something` is: // An example of the structure to match `?key=value&topic=api&query=something` is:
// //
// ```json // ```json
@@ -808,19 +809,29 @@ func (m MatchQuery) Match(r *http.Request) bool {
return false return false
} }
for param, vals := range m { for param, allowedVals := range m {
param = repl.ReplaceAll(param, "") param = repl.ReplaceAll(param, "")
paramVal, found := parsed[param] incomingVals, found := parsed[param]
if found { if found {
for _, v := range vals { for _, allowedVal := range allowedVals {
v = repl.ReplaceAll(v, "") allowedVal = repl.ReplaceAll(allowedVal, "")
if paramVal[0] == v || v == "*" { if allowedVal == "*" {
return true
}
matched := true
for _, incomingVal := range incomingVals {
if incomingVal != allowedVal {
matched = false
break
}
}
if matched {
return true return true
} }
} }
} }
} }
return len(m) == 0 && len(r.URL.Query()) == 0 return len(m) == 0 && len(parsed) == 0
} }
// CELLibrary produces options that expose this matcher for use in CEL // CELLibrary produces options that expose this matcher for use in CEL
+26 -2
View File
@@ -718,7 +718,7 @@ func TestQueryMatcher(t *testing.T) {
expect: true, expect: true,
}, },
{ {
scenario: "non match against a wildcarded", scenario: "non match against a wildcard",
match: MatchQuery{"debug": []string{"*"}}, match: MatchQuery{"debug": []string{"*"}},
input: "/?other=something", input: "/?other=something",
expect: false, expect: false,
@@ -765,6 +765,30 @@ func TestQueryMatcher(t *testing.T) {
input: "/?somekey=1", input: "/?somekey=1",
expect: true, expect: true,
}, },
{
scenario: "don't match conflicting values",
match: MatchQuery{"a": []string{"1"}},
input: "/?a=1&a=2",
expect: false,
},
{
scenario: "conflicting values are ambiguous with multiple match values",
match: MatchQuery{"a": []string{"1", "2"}},
input: "/?a=1&a=2",
expect: false,
},
{
scenario: "repeated kv pairs in URI",
match: MatchQuery{"a": []string{"1"}},
input: "/?a=1&a=1",
expect: true,
},
{
scenario: "TODO: it's unclear whether the values should be AND'ed or OR'ed", // perhaps multiple query matchers could be used to "and"
match: MatchQuery{"a": []string{"1", "2"}},
input: "/?a=2",
expect: true,
},
} { } {
u, _ := url.Parse(tc.input) u, _ := url.Parse(tc.input)
@@ -777,7 +801,7 @@ func TestQueryMatcher(t *testing.T) {
req = req.WithContext(ctx) req = req.WithContext(ctx)
actual := tc.match.Match(req) actual := tc.match.Match(req)
if actual != tc.expect { if actual != tc.expect {
t.Errorf("Test %d %v: Expected %t, got %t for '%s'", i, tc.match, tc.expect, actual, tc.input) t.Errorf("Test %d %v: Expected %t, got %t for '%s' (%s)", i, tc.match, tc.expect, actual, tc.input, tc.scenario)
continue continue
} }
} }
-1
View File
@@ -268,7 +268,6 @@ func init() {
// {{humanize "time" "Fri, 05 May 2022 15:04:05 +0200"}} // {{humanize "time" "Fri, 05 May 2022 15:04:05 +0200"}}
// {{humanize "time:2006-Jan-02" "2022-May-05"}} // {{humanize "time:2006-Jan-02" "2022-May-05"}}
// ``` // ```
type Templates struct { type Templates struct {
// The root path from which to load files. Required if template functions // The root path from which to load files. Required if template functions
// accessing the file system are used (such as include). Default is // accessing the file system are used (such as include). Default is