@marcel91200 / caddy Mirror · read-only
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 11, 01:00 UTC

master
go 230 lines 6.09 KB
Raw
1 package maphandler
2
3 import (
4 "context"
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 TestProvisionDestinations(t *testing.T) {
47 for _, tc := range []struct {
48 name string
49 destination string
50 want string
51 wantErr bool
52 }{
53 {name: "valid placeholder", destination: "{output}", want: "output"},
54 {name: "trailing text", destination: "{output}suffix", wantErr: true},
55 {name: "leading text", destination: "prefix{output}", wantErr: true},
56 {name: "missing opening brace", destination: "output}", wantErr: true},
57 {name: "missing closing brace", destination: "{output", wantErr: true},
58 {name: "double closing brace", destination: "{output}}", wantErr: true},
59 {name: "double opening brace", destination: "{{output}", wantErr: true},
60 {name: "nested braces", destination: "{out{put}}", wantErr: true},
61 {name: "empty braces", destination: "{}", wantErr: true},
62 {name: "no braces", destination: "output", wantErr: true},
63 } {
64 t.Run(tc.name, func(t *testing.T) {
65 h := Handler{
66 Source: "{http.request.uri.path}",
67 Destinations: []string{tc.destination},
68 Mappings: []Mapping{
69 {
70 Input: "/foo",
71 Outputs: []any{"FOO"},
72 },
73 },
74 }
75 err := h.Provision(caddy.Context{})
76 if tc.wantErr {
77 if err == nil {
78 t.Fatalf("expected error for destination %q, but got none (stored %q)", tc.destination, h.Destinations[0])
79 }
80 return
81 }
82 if err != nil {
83 t.Fatalf("unexpected error for destination %q: %v", tc.destination, err)
84 }
85 if h.Destinations[0] != tc.want {
86 t.Fatalf("expected destination %q, got %q", tc.want, h.Destinations[0])
87 }
88 })
89 }
90 }
91
92 func TestHandler(t *testing.T) {
93 for i, tc := range []struct {
94 handler Handler
95 reqURI string
96 expect map[string]any
97 }{
98 {
99 reqURI: "/foo",
100 handler: Handler{
101 Source: "{http.request.uri.path}",
102 Destinations: []string{"{output}"},
103 Mappings: []Mapping{
104 {
105 Input: "/foo",
106 Outputs: []any{"FOO"},
107 },
108 },
109 },
110 expect: map[string]any{
111 "output": "FOO",
112 },
113 },
114 {
115 reqURI: "/abcdef",
116 handler: Handler{
117 Source: "{http.request.uri.path}",
118 Destinations: []string{"{output}"},
119 Mappings: []Mapping{
120 {
121 InputRegexp: "(/abc)",
122 Outputs: []any{"ABC"},
123 },
124 },
125 },
126 expect: map[string]any{
127 "output": "ABC",
128 },
129 },
130 {
131 reqURI: "/ABCxyzDEF",
132 handler: Handler{
133 Source: "{http.request.uri.path}",
134 Destinations: []string{"{output}"},
135 Mappings: []Mapping{
136 {
137 InputRegexp: "(xyz)",
138 Outputs: []any{"...${1}..."},
139 },
140 },
141 },
142 expect: map[string]any{
143 "output": "...xyz...",
144 },
145 },
146 {
147 // Test case from https://caddy.community/t/map-directive-and-regular-expressions/13866/14?u=matt
148 reqURI: "/?s=0%27+AND+%28SELECT+0+FROM+%28SELECT+count%28%2A%29%2C+CONCAT%28%28SELECT+%40%40version%29%2C+0x23%2C+FLOOR%28RAND%280%29%2A2%29%29+AS+x+FROM+information_schema.columns+GROUP+BY+x%29+y%29+-+-+%27",
149 handler: Handler{
150 Source: "{http.request.uri}",
151 Destinations: []string{"{output}"},
152 Mappings: []Mapping{
153 {
154 InputRegexp: "(?i)(\\^|`|<|>|%|\\\\|\\{|\\}|\\|)",
155 Outputs: []any{"3"},
156 },
157 },
158 },
159 expect: map[string]any{
160 "output": "3",
161 },
162 },
163 {
164 reqURI: "/foo",
165 handler: Handler{
166 Source: "{http.request.uri.path}",
167 Destinations: []string{"{output}"},
168 Mappings: []Mapping{
169 {
170 Input: "/foo",
171 Outputs: []any{"{testvar}"},
172 },
173 },
174 },
175 expect: map[string]any{
176 "output": "testing",
177 },
178 },
179 {
180 reqURI: "/foo",
181 handler: Handler{
182 Source: "{http.request.uri.path}",
183 Destinations: []string{"{output}"},
184 Defaults: []string{"default"},
185 },
186 expect: map[string]any{
187 "output": "default",
188 },
189 },
190 {
191 reqURI: "/foo",
192 handler: Handler{
193 Source: "{http.request.uri.path}",
194 Destinations: []string{"{output}"},
195 Defaults: []string{"{testvar}"},
196 },
197 expect: map[string]any{
198 "output": "testing",
199 },
200 },
201 } {
202 if err := tc.handler.Provision(caddy.Context{}); err != nil {
203 t.Fatalf("Test %d: Provisioning handler: %v", i, err)
204 }
205
206 req, err := http.NewRequest(http.MethodGet, tc.reqURI, nil)
207 if err != nil {
208 t.Fatalf("Test %d: Creating request: %v", i, err)
209 }
210 repl := caddyhttp.NewTestReplacer(req)
211 repl.Set("testvar", "testing")
212 ctx := context.WithValue(req.Context(), caddy.ReplacerCtxKey, repl)
213 req = req.WithContext(ctx)
214
215 rr := httptest.NewRecorder()
216 noop := caddyhttp.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) error { return nil })
217
218 if err := tc.handler.ServeHTTP(rr, req, noop); err != nil {
219 t.Errorf("Test %d: Handler returned error: %v", i, err)
220 continue
221 }
222
223 for key, expected := range tc.expect {
224 actual, _ := repl.Get(key)
225 if !reflect.DeepEqual(actual, expected) {
226 t.Errorf("Test %d: Expected %#v but got %#v for {%s}", i, expected, actual, key)
227 }
228 }
229 }
230 }