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

httpcaddyfile: Don't lowercase placeholder contents (fixes #3264)

Matthew Holt committed Apr 14, 2020 at 16:11 UTC 829e36d535cf5bbff7cf0f510608e6fca956cec4
3 files changed +54 -3
caddyconfig/httpcaddyfile/addresses.go
+31 -2
@@ -20,6 +20,7 @@ import (
20 "reflect"
21 "strconv"
22 "strings"
23 + "unicode"
24
25 "github.com/caddyserver/caddy/v2"
26 "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
@@ -333,8 +334,8 @@ func (a Address) Normalize() Address {
334
335 return Address{
336 Original: a.Original,
336 - Scheme: strings.ToLower(a.Scheme),
337 - Host: strings.ToLower(host),
337 + Scheme: lowerExceptPlaceholders(a.Scheme),
338 + Host: lowerExceptPlaceholders(host),
339 Port: a.Port,
340 Path: path,
341 }
@@ -361,3 +362,31 @@ func (a Address) Key() string {
362 }
363 return res
364 }
365 +
366 +// lowerExceptPlaceholders lowercases s except within
367 +// placeholders (substrings in non-escaped '{ }' spans).
368 +// See https://github.com/caddyserver/caddy/issues/3264
369 +func lowerExceptPlaceholders(s string) string {
370 + var sb strings.Builder
371 + var escaped, inPlaceholder bool
372 + for _, ch := range s {
373 + if ch == '\\' && !escaped {
374 + escaped = true
375 + sb.WriteRune(ch)
376 + continue
377 + }
378 + if ch == '{' && !escaped {
379 + inPlaceholder = true
380 + }
381 + if ch == '}' && inPlaceholder && !escaped {
382 + inPlaceholder = false
383 + }
384 + if inPlaceholder {
385 + sb.WriteRune(ch)
386 + } else {
387 + sb.WriteRune(unicode.ToLower(ch))
388 + }
389 + escaped = false
390 + }
391 + return sb.String()
392 +}
caddyconfig/httpcaddyfile/addresses_test.go
+21 -1
@@ -108,6 +108,10 @@ func TestKeyNormalization(t *testing.T) {
108 input string
109 expect string
110 }{
111 + {
112 + input: "example.com",
113 + expect: "example.com",
114 + },
115 {
116 input: "http://host:1234/path",
117 expect: "http://host:1234/path",
@@ -124,6 +128,22 @@ func TestKeyNormalization(t *testing.T) {
128 input: "A:2015/Path",
129 expect: "a:2015/Path",
130 },
131 + {
132 + input: "sub.{env.MY_DOMAIN}",
133 + expect: "sub.{env.MY_DOMAIN}",
134 + },
135 + {
136 + input: "sub.ExAmPle",
137 + expect: "sub.example",
138 + },
139 + {
140 + input: "sub.\\{env.MY_DOMAIN\\}",
141 + expect: "sub.\\{env.my_domain\\}",
142 + },
143 + {
144 + input: "sub.{env.MY_DOMAIN}.com",
145 + expect: "sub.{env.MY_DOMAIN}.com",
146 + },
147 {
148 input: ":80",
149 expect: ":80",
@@ -156,7 +176,7 @@ func TestKeyNormalization(t *testing.T) {
176 continue
177 }
178 if actual := addr.Normalize().Key(); actual != tc.expect {
159 - t.Errorf("Test %d: Normalized key for address '%s' was '%s' but expected '%s'", i, tc.input, actual, tc.expect)
179 + t.Errorf("Test %d: Input '%s': Expected '%s' but got '%s'", i, tc.input, tc.expect, actual)
180 }
181
182 }
modules/caddyhttp/caddyauth/caddyauth.go
+2
@@ -29,6 +29,8 @@ func init() {
29
30 // Authentication is a middleware which provides user authentication.
31 // Rejects requests with HTTP 401 if the request is not authenticated.
32 +//
33 +// Its API is still experimental and may be subject to change.
34 type Authentication struct {
35 // A set of authentication providers. If none are specified,
36 // all requests will always be unauthenticated.