@marcel91200 / caddy Mirror · read-only / commits / 288216e1
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 12, 23:15 UTC

httpcaddyfile: Stricter errors for site and upstream address schemes (#5757)

Co-authored-by: Mohammed Al Sahaf <msaa1990@gmail.com> Co-authored-by: Francis Lavoie <lavofr@gmail.com>

Karun Agarwal committed Aug 19, 2023 at 16:58 UTC 288216e1fbf25ebe11fcea7c71be526c4cd0dcce
3 files changed +374 -2
caddyconfig/httpcaddyfile/addresses.go
+11
@@ -197,6 +197,17 @@ func (st *ServerType) listenerAddrsForServerBlockKey(sblock serverBlock, key str
197 }
198 addr = addr.Normalize()
199
200 + switch addr.Scheme {
201 + case "wss":
202 + return nil, fmt.Errorf("the scheme wss:// is only supported in browsers; use https:// instead")
203 + case "ws":
204 + return nil, fmt.Errorf("the scheme ws:// is only supported in browsers; use http:// instead")
205 + case "https", "http", "":
206 + // Do nothing or handle the valid schemes
207 + default:
208 + return nil, fmt.Errorf("unsupported URL scheme %s://", addr.Scheme)
209 + }
210 +
211 // figure out the HTTP and HTTPS ports; either
212 // use defaults, or override with user config
213 httpPort, httpsPort := strconv.Itoa(caddyhttp.DefaultHTTPPort), strconv.Itoa(caddyhttp.DefaultHTTPSPort)
caddytest/integration/caddyfile_test.go
+349
@@ -135,3 +135,352 @@ func TestReplIndex(t *testing.T) {
135 // act and assert
136 tester.AssertGetResponse("http://localhost:9080/", 200, "")
137 }
138 +
139 +func TestInvalidPrefix(t *testing.T) {
140 + type testCase struct {
141 + config, expectedError string
142 + }
143 +
144 + failureCases := []testCase{
145 + {
146 + config: `wss://localhost`,
147 + expectedError: `the scheme wss:// is only supported in browsers; use https:// instead`,
148 + },
149 + {
150 + config: `ws://localhost`,
151 + expectedError: `the scheme ws:// is only supported in browsers; use http:// instead`,
152 + },
153 + {
154 + config: `someInvalidPrefix://localhost`,
155 + expectedError: "unsupported URL scheme someinvalidprefix://",
156 + },
157 + {
158 + config: `h2c://localhost`,
159 + expectedError: `unsupported URL scheme h2c://`,
160 + },
161 + {
162 + config: `localhost, wss://localhost`,
163 + expectedError: `the scheme wss:// is only supported in browsers; use https:// instead`,
164 + },
165 + {
166 + config: `localhost {
167 + reverse_proxy ws://localhost"
168 + }`,
169 + expectedError: `the scheme ws:// is only supported in browsers; use http:// instead`,
170 + },
171 + {
172 + config: `localhost {
173 + reverse_proxy someInvalidPrefix://localhost"
174 + }`,
175 + expectedError: `unsupported URL scheme someinvalidprefix://`,
176 + },
177 + }
178 +
179 + for _, failureCase := range failureCases {
180 + caddytest.AssertLoadError(t, failureCase.config, "caddyfile", failureCase.expectedError)
181 + }
182 +}
183 +
184 +func TestValidPrefix(t *testing.T) {
185 + type testCase struct {
186 + rawConfig, expectedResponse string
187 + }
188 +
189 + successCases := []testCase{
190 + {
191 + "localhost",
192 + `{
193 + "apps": {
194 + "http": {
195 + "servers": {
196 + "srv0": {
197 + "listen": [
198 + ":443"
199 + ],
200 + "routes": [
201 + {
202 + "match": [
203 + {
204 + "host": [
205 + "localhost"
206 + ]
207 + }
208 + ],
209 + "terminal": true
210 + }
211 + ]
212 + }
213 + }
214 + }
215 + }
216 +}`,
217 + },
218 + {
219 + "https://localhost",
220 + `{
221 + "apps": {
222 + "http": {
223 + "servers": {
224 + "srv0": {
225 + "listen": [
226 + ":443"
227 + ],
228 + "routes": [
229 + {
230 + "match": [
231 + {
232 + "host": [
233 + "localhost"
234 + ]
235 + }
236 + ],
237 + "terminal": true
238 + }
239 + ]
240 + }
241 + }
242 + }
243 + }
244 +}`,
245 + },
246 + {
247 + "http://localhost",
248 + `{
249 + "apps": {
250 + "http": {
251 + "servers": {
252 + "srv0": {
253 + "listen": [
254 + ":80"
255 + ],
256 + "routes": [
257 + {
258 + "match": [
259 + {
260 + "host": [
261 + "localhost"
262 + ]
263 + }
264 + ],
265 + "terminal": true
266 + }
267 + ]
268 + }
269 + }
270 + }
271 + }
272 +}`,
273 + },
274 + {
275 + `localhost {
276 + reverse_proxy http://localhost:3000
277 + }`,
278 + `{
279 + "apps": {
280 + "http": {
281 + "servers": {
282 + "srv0": {
283 + "listen": [
284 + ":443"
285 + ],
286 + "routes": [
287 + {
288 + "match": [
289 + {
290 + "host": [
291 + "localhost"
292 + ]
293 + }
294 + ],
295 + "handle": [
296 + {
297 + "handler": "subroute",
298 + "routes": [
299 + {
300 + "handle": [
301 + {
302 + "handler": "reverse_proxy",
303 + "upstreams": [
304 + {
305 + "dial": "localhost:3000"
306 + }
307 + ]
308 + }
309 + ]
310 + }
311 + ]
312 + }
313 + ],
314 + "terminal": true
315 + }
316 + ]
317 + }
318 + }
319 + }
320 + }
321 +}`,
322 + },
323 + {
324 + `localhost {
325 + reverse_proxy https://localhost:3000
326 + }`,
327 + `{
328 + "apps": {
329 + "http": {
330 + "servers": {
331 + "srv0": {
332 + "listen": [
333 + ":443"
334 + ],
335 + "routes": [
336 + {
337 + "match": [
338 + {
339 + "host": [
340 + "localhost"
341 + ]
342 + }
343 + ],
344 + "handle": [
345 + {
346 + "handler": "subroute",
347 + "routes": [
348 + {
349 + "handle": [
350 + {
351 + "handler": "reverse_proxy",
352 + "transport": {
353 + "protocol": "http",
354 + "tls": {}
355 + },
356 + "upstreams": [
357 + {
358 + "dial": "localhost:3000"
359 + }
360 + ]
361 + }
362 + ]
363 + }
364 + ]
365 + }
366 + ],
367 + "terminal": true
368 + }
369 + ]
370 + }
371 + }
372 + }
373 + }
374 +}`,
375 + },
376 + {
377 + `localhost {
378 + reverse_proxy h2c://localhost:3000
379 + }`,
380 + `{
381 + "apps": {
382 + "http": {
383 + "servers": {
384 + "srv0": {
385 + "listen": [
386 + ":443"
387 + ],
388 + "routes": [
389 + {
390 + "match": [
391 + {
392 + "host": [
393 + "localhost"
394 + ]
395 + }
396 + ],
397 + "handle": [
398 + {
399 + "handler": "subroute",
400 + "routes": [
401 + {
402 + "handle": [
403 + {
404 + "handler": "reverse_proxy",
405 + "transport": {
406 + "protocol": "http",
407 + "versions": [
408 + "h2c",
409 + "2"
410 + ]
411 + },
412 + "upstreams": [
413 + {
414 + "dial": "localhost:3000"
415 + }
416 + ]
417 + }
418 + ]
419 + }
420 + ]
421 + }
422 + ],
423 + "terminal": true
424 + }
425 + ]
426 + }
427 + }
428 + }
429 + }
430 +}`,
431 + },
432 + {
433 + `localhost {
434 + reverse_proxy localhost:3000
435 + }`,
436 + `{
437 + "apps": {
438 + "http": {
439 + "servers": {
440 + "srv0": {
441 + "listen": [
442 + ":443"
443 + ],
444 + "routes": [
445 + {
446 + "match": [
447 + {
448 + "host": [
449 + "localhost"
450 + ]
451 + }
452 + ],
453 + "handle": [
454 + {
455 + "handler": "subroute",
456 + "routes": [
457 + {
458 + "handle": [
459 + {
460 + "handler": "reverse_proxy",
461 + "upstreams": [
462 + {
463 + "dial": "localhost:3000"
464 + }
465 + ]
466 + }
467 + ]
468 + }
469 + ]
470 + }
471 + ],
472 + "terminal": true
473 + }
474 + ]
475 + }
476 + }
477 + }
478 + }
479 +}`,
480 + },
481 + }
482 +
483 + for _, successCase := range successCases {
484 + caddytest.AssertAdapt(t, successCase.rawConfig, "caddyfile", successCase.expectedResponse)
485 + }
486 +}
modules/caddyhttp/reverseproxy/caddyfile.go
+14 -2
@@ -155,6 +155,18 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
155 // the underlying JSON does not yet support different
156 // transports (protocols or schemes) to each backend,
157 // so we remember the last one we see and compare them
158 +
159 + switch pa.scheme {
160 + case "wss":
161 + return d.Errf("the scheme wss:// is only supported in browsers; use https:// instead")
162 + case "ws":
163 + return d.Errf("the scheme ws:// is only supported in browsers; use http:// instead")
164 + case "https", "http", "h2c", "":
165 + // Do nothing or handle the valid schemes
166 + default:
167 + return d.Errf("unsupported URL scheme %s://", pa.scheme)
168 + }
169 +
170 if commonScheme != "" && pa.scheme != commonScheme {
171 return d.Errf("for now, all proxy upstreams must use the same scheme (transport protocol); expecting '%s://' but got '%s://'",
172 commonScheme, pa.scheme)
@@ -193,7 +205,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
205 for _, up := range d.RemainingArgs() {
206 err := appendUpstream(up)
207 if err != nil {
196 - return err
208 + return fmt.Errorf("parsing upstream '%s': %w", up, err)
209 }
210 }
211
@@ -217,7 +229,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
229 for _, up := range args {
230 err := appendUpstream(up)
231 if err != nil {
220 - return err
232 + return fmt.Errorf("parsing upstream '%s': %w", up, err)
233 }
234 }
235