Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 04:45 UTC
map: Distinguish duplicate literal and regexp inputs (#8067)
Hitanshu committed
Sep 27, 2026 at 05:03 UTC
ea1e94b89972b83b189cbb946352abd9acec0f8c
2 files changed
+36
-3
modules/caddyhttp/map/map.go
+4
-3
@@ -94,7 +94,8 @@ func (h *Handler) Validate() error {
94
return fmt.Errorf("%d destinations != %d defaults", nDest, nDef)
95
}
96
97
- seen := make(map[string]int)
97
+ seenLiterals := make(map[string]int)
98
+ seenRegexps := make(map[string]int)
99
for i, m := range h.Mappings {
100
// prevent confusing/ambiguous mappings
101
if m.Input != "" && m.InputRegexp != "" {
@@ -102,9 +103,9 @@ func (h *Handler) Validate() error {
103
}
104
105
// prevent duplicate mappings
105
- input := m.Input
106
+ input, seen := m.Input, seenLiterals
107
if m.InputRegexp != "" {
107
- input = m.InputRegexp
108
+ input, seen = m.InputRegexp, seenRegexps
109
}
110
if prev, ok := seen[input]; ok {
111
return fmt.Errorf("mapping %d has a duplicate input '%s' previously used with mapping %d", i, input, prev)
modules/caddyhttp/map/map_test.go
+32
@@ -5,12 +5,44 @@ import (
5
"net/http"
6
"net/http/httptest"
7
"reflect"
8
+ "strings"
9
"testing"
10
11
"github.com/caddyserver/caddy/v2"
12
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
13
)
14
15
+func TestValidateDuplicateInputs(t *testing.T) {
16
+ for _, tc := range []struct {
17
+ name string
18
+ first Mapping
19
+ second Mapping
20
+ wantErr bool
21
+ }{
22
+ {name: "duplicate literals", first: Mapping{Input: "/abc"}, second: Mapping{Input: "/abc"}, wantErr: true},
23
+ {name: "duplicate regexps", first: Mapping{InputRegexp: "/abc"}, second: Mapping{InputRegexp: "/abc"}, wantErr: true},
24
+ {name: "literal then regexp", first: Mapping{Input: "/abc"}, second: Mapping{InputRegexp: "/abc"}},
25
+ {name: "regexp then literal", first: Mapping{InputRegexp: "/abc"}, second: Mapping{Input: "/abc"}},
26
+ } {
27
+ t.Run(tc.name, func(t *testing.T) {
28
+ tc.first.Outputs = []any{"first"}
29
+ tc.second.Outputs = []any{"second"}
30
+ h := Handler{
31
+ Destinations: []string{"{output}"},
32
+ Mappings: []Mapping{tc.first, tc.second},
33
+ }
34
+ err := h.Validate()
35
+ if tc.wantErr {
36
+ if err == nil || !strings.Contains(err.Error(), "duplicate input '/abc'") {
37
+ t.Fatalf("expected duplicate input error, got %v", err)
38
+ }
39
+ } else if err != nil {
40
+ t.Fatalf("unexpected validation error: %v", err)
41
+ }
42
+ })
43
+ }
44
+}
45
+
46
func TestHandler(t *testing.T) {
47
for i, tc := range []struct {
48
handler Handler