mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-27 06:03:48 +03:00
caddyhttp: Make query matcher more efficient
Only parse query string once
This commit is contained in:
parent
c2bbe42fc3
commit
04a14ee37a
1 changed files with 17 additions and 1 deletions
|
@ -103,6 +103,9 @@ type (
|
||||||
// "query": ["*"]
|
// "query": ["*"]
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
|
//
|
||||||
|
// Invalid query strings, including those with bad escapings or illegal characters
|
||||||
|
// like semicolons, will fail to parse and thus fail to match.
|
||||||
MatchQuery url.Values
|
MatchQuery url.Values
|
||||||
|
|
||||||
// MatchHeader matches requests by header fields. The key is the field
|
// MatchHeader matches requests by header fields. The key is the field
|
||||||
|
@ -625,9 +628,22 @@ func (m *MatchQuery) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||||
// Match returns true if r matches m. An empty m matches an empty query string.
|
// Match returns true if r matches m. An empty m matches an empty query string.
|
||||||
func (m MatchQuery) Match(r *http.Request) bool {
|
func (m MatchQuery) Match(r *http.Request) bool {
|
||||||
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
|
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
|
||||||
|
|
||||||
|
// parse query string just once, for efficiency
|
||||||
|
parsed, err := url.ParseQuery(r.URL.RawQuery)
|
||||||
|
if err != nil {
|
||||||
|
// Illegal query string. Likely bad escape sequence or syntax.
|
||||||
|
// Note that semicolons in query string have a controversial history. Summaries:
|
||||||
|
// - https://github.com/golang/go/issues/50034
|
||||||
|
// - https://github.com/golang/go/issues/25192
|
||||||
|
// W3C recommendations are flawed and ambiguous, and different servers handle semicolons differently.
|
||||||
|
// Filippo Valsorda rightly wrote: "Relying on parser alignment for security is doomed."
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
for param, vals := range m {
|
for param, vals := range m {
|
||||||
param = repl.ReplaceAll(param, "")
|
param = repl.ReplaceAll(param, "")
|
||||||
paramVal, found := r.URL.Query()[param]
|
paramVal, found := parsed[param]
|
||||||
if found {
|
if found {
|
||||||
for _, v := range vals {
|
for _, v := range vals {
|
||||||
v = repl.ReplaceAll(v, "")
|
v = repl.ReplaceAll(v, "")
|
||||||
|
|
Loading…
Reference in a new issue