Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 12, 10:45 UTC
caddyhttp: Convert IDNs to ASCII when provisioning Host matcher
Matthew Holt committed
Jun 18, 2024 at 14:43 UTC
99dcdf7e426f0dcbdffe510f241ae8a4fd5a56e6
2 files changed
+23
-6
modules/caddyhttp/matchers.go
+14
-6
@@ -34,6 +34,7 @@ import (
34
"github.com/google/cel-go/cel"
35
"github.com/google/cel-go/common/types"
36
"github.com/google/cel-go/common/types/ref"
37
+ "golang.org/x/net/idna"
38
39
"github.com/caddyserver/caddy/v2"
40
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
@@ -239,13 +240,20 @@ func (m *MatchHost) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
240
func (m MatchHost) Provision(_ caddy.Context) error {
241
// check for duplicates; they are nonsensical and reduce efficiency
242
// (we could just remove them, but the user should know their config is erroneous)
242
- seen := make(map[string]int)
243
- for i, h := range m {
244
- h = strings.ToLower(h)
245
- if firstI, ok := seen[h]; ok {
246
- return fmt.Errorf("host at index %d is repeated at index %d: %s", firstI, i, h)
243
+ seen := make(map[string]int, len(m))
244
+ for i, host := range m {
245
+ asciiHost, err := idna.ToASCII(host)
246
+ if err != nil {
247
+ return fmt.Errorf("converting hostname '%s' to ASCII: %v", host, err)
248
+ }
249
+ if asciiHost != host {
250
+ m[i] = asciiHost
251
+ }
252
+ normalizedHost := strings.ToLower(asciiHost)
253
+ if firstI, ok := seen[normalizedHost]; ok {
254
+ return fmt.Errorf("host at index %d is repeated at index %d: %s", firstI, i, host)
255
}
248
- seen[h] = i
256
+ seen[normalizedHost] = i
257
}
258
259
if m.large() {
modules/caddyhttp/matchers_test.go
+9
@@ -78,6 +78,11 @@ func TestHostMatcher(t *testing.T) {
78
input: "bar.example.com",
79
expect: false,
80
},
81
+ {
82
+ match: MatchHost{"éxàmplê.com"},
83
+ input: "xn--xmpl-0na6cm.com",
84
+ expect: true,
85
+ },
86
{
87
match: MatchHost{"*.example.com"},
88
input: "example.com",
@@ -149,6 +154,10 @@ func TestHostMatcher(t *testing.T) {
154
ctx := context.WithValue(req.Context(), caddy.ReplacerCtxKey, repl)
155
req = req.WithContext(ctx)
156
157
+ if err := tc.match.Provision(caddy.Context{}); err != nil {
158
+ t.Errorf("Test %d %v: provisioning failed: %v", i, tc.match, err)
159
+ }
160
+
161
actual := tc.match.Match(req)
162
if actual != tc.expect {
163
t.Errorf("Test %d %v: Expected %t, got %t for '%s'", i, tc.match, tc.expect, actual, tc.input)