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

reverseproxy: Fix host and port on requests; fix Caddyfile parser

Matthew Holt committed Sep 11, 2019 at 18:53 UTC 758269124ef5d6d83cb4e8d8eeb095f5b025250e
2 files changed +128 -94
modules/caddyhttp/reverseproxy/caddyfile.go
+95 -93
@@ -376,108 +376,110 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
376 // }
377 //
378 func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
379 - for d.NextBlock(0) {
380 - switch d.Val() {
381 - case "read_buffer":
382 - if !d.NextArg() {
383 - return d.ArgErr()
384 - }
385 - size, err := humanize.ParseBytes(d.Val())
386 - if err != nil {
387 - return d.Errf("invalid read buffer size '%s': %v", d.Val(), err)
388 - }
389 - h.ReadBufferSize = int(size)
379 + for d.Next() {
380 + for d.NextBlock(0) {
381 + switch d.Val() {
382 + case "read_buffer":
383 + if !d.NextArg() {
384 + return d.ArgErr()
385 + }
386 + size, err := humanize.ParseBytes(d.Val())
387 + if err != nil {
388 + return d.Errf("invalid read buffer size '%s': %v", d.Val(), err)
389 + }
390 + h.ReadBufferSize = int(size)
391
391 - case "write_buffer":
392 - if !d.NextArg() {
393 - return d.ArgErr()
394 - }
395 - size, err := humanize.ParseBytes(d.Val())
396 - if err != nil {
397 - return d.Errf("invalid write buffer size '%s': %v", d.Val(), err)
398 - }
399 - h.WriteBufferSize = int(size)
392 + case "write_buffer":
393 + if !d.NextArg() {
394 + return d.ArgErr()
395 + }
396 + size, err := humanize.ParseBytes(d.Val())
397 + if err != nil {
398 + return d.Errf("invalid write buffer size '%s': %v", d.Val(), err)
399 + }
400 + h.WriteBufferSize = int(size)
401
401 - case "dial_timeout":
402 - if !d.NextArg() {
403 - return d.ArgErr()
404 - }
405 - dur, err := time.ParseDuration(d.Val())
406 - if err != nil {
407 - return d.Errf("bad timeout value '%s': %v", d.Val(), err)
408 - }
409 - h.DialTimeout = caddy.Duration(dur)
402 + case "dial_timeout":
403 + if !d.NextArg() {
404 + return d.ArgErr()
405 + }
406 + dur, err := time.ParseDuration(d.Val())
407 + if err != nil {
408 + return d.Errf("bad timeout value '%s': %v", d.Val(), err)
409 + }
410 + h.DialTimeout = caddy.Duration(dur)
411
411 - case "tls_client_auth":
412 - args := d.RemainingArgs()
413 - if len(args) != 2 {
414 - return d.ArgErr()
415 - }
416 - if h.TLS == nil {
417 - h.TLS = new(TLSConfig)
418 - }
419 - h.TLS.ClientCertificateFile = args[0]
420 - h.TLS.ClientCertificateKeyFile = args[1]
412 + case "tls_client_auth":
413 + args := d.RemainingArgs()
414 + if len(args) != 2 {
415 + return d.ArgErr()
416 + }
417 + if h.TLS == nil {
418 + h.TLS = new(TLSConfig)
419 + }
420 + h.TLS.ClientCertificateFile = args[0]
421 + h.TLS.ClientCertificateKeyFile = args[1]
422
422 - case "tls":
423 - if h.TLS == nil {
424 - h.TLS = new(TLSConfig)
425 - }
423 + case "tls":
424 + if h.TLS == nil {
425 + h.TLS = new(TLSConfig)
426 + }
427
427 - case "tls_insecure_skip_verify":
428 - if d.NextArg() {
429 - return d.ArgErr()
430 - }
431 - if h.TLS == nil {
432 - h.TLS = new(TLSConfig)
433 - }
434 - h.TLS.InsecureSkipVerify = true
428 + case "tls_insecure_skip_verify":
429 + if d.NextArg() {
430 + return d.ArgErr()
431 + }
432 + if h.TLS == nil {
433 + h.TLS = new(TLSConfig)
434 + }
435 + h.TLS.InsecureSkipVerify = true
436
436 - case "tls_timeout":
437 - if !d.NextArg() {
438 - return d.ArgErr()
439 - }
440 - dur, err := time.ParseDuration(d.Val())
441 - if err != nil {
442 - return d.Errf("bad timeout value '%s': %v", d.Val(), err)
443 - }
444 - if h.TLS == nil {
445 - h.TLS = new(TLSConfig)
446 - }
447 - h.TLS.HandshakeTimeout = caddy.Duration(dur)
437 + case "tls_timeout":
438 + if !d.NextArg() {
439 + return d.ArgErr()
440 + }
441 + dur, err := time.ParseDuration(d.Val())
442 + if err != nil {
443 + return d.Errf("bad timeout value '%s': %v", d.Val(), err)
444 + }
445 + if h.TLS == nil {
446 + h.TLS = new(TLSConfig)
447 + }
448 + h.TLS.HandshakeTimeout = caddy.Duration(dur)
449
449 - case "keepalive":
450 - if !d.NextArg() {
451 - return d.ArgErr()
452 - }
453 - if h.KeepAlive == nil {
454 - h.KeepAlive = new(KeepAlive)
455 - }
456 - if d.Val() == "off" {
457 - var disable bool
458 - h.KeepAlive.Enabled = &disable
459 - }
460 - dur, err := time.ParseDuration(d.Val())
461 - if err != nil {
462 - return d.Errf("bad duration value '%s': %v", d.Val(), err)
463 - }
464 - h.KeepAlive.IdleConnTimeout = caddy.Duration(dur)
450 + case "keepalive":
451 + if !d.NextArg() {
452 + return d.ArgErr()
453 + }
454 + if h.KeepAlive == nil {
455 + h.KeepAlive = new(KeepAlive)
456 + }
457 + if d.Val() == "off" {
458 + var disable bool
459 + h.KeepAlive.Enabled = &disable
460 + }
461 + dur, err := time.ParseDuration(d.Val())
462 + if err != nil {
463 + return d.Errf("bad duration value '%s': %v", d.Val(), err)
464 + }
465 + h.KeepAlive.IdleConnTimeout = caddy.Duration(dur)
466
466 - case "keepalive_idle_conns":
467 - if !d.NextArg() {
468 - return d.ArgErr()
469 - }
470 - num, err := strconv.Atoi(d.Val())
471 - if err != nil {
472 - return d.Errf("bad integer value '%s': %v", d.Val(), err)
473 - }
474 - if h.KeepAlive == nil {
475 - h.KeepAlive = new(KeepAlive)
476 - }
477 - h.KeepAlive.MaxIdleConns = num
467 + case "keepalive_idle_conns":
468 + if !d.NextArg() {
469 + return d.ArgErr()
470 + }
471 + num, err := strconv.Atoi(d.Val())
472 + if err != nil {
473 + return d.Errf("bad integer value '%s': %v", d.Val(), err)
474 + }
475 + if h.KeepAlive == nil {
476 + h.KeepAlive = new(KeepAlive)
477 + }
478 + h.KeepAlive.MaxIdleConns = num
479
479 - default:
480 - return d.Errf("unrecognized subdirective %s", d.Val())
480 + default:
481 + return d.Errf("unrecognized subdirective %s", d.Val())
482 + }
483 }
484 }
485 return nil
modules/caddyhttp/reverseproxy/reverseproxy.go
+33 -1
@@ -145,6 +145,26 @@ func (h *Handler) Provision(ctx caddy.Context) error {
145
146 var allUpstreams []*Upstream
147 for _, upstream := range h.Upstreams {
148 + // if a port was not specified (and the network type uses
149 + // ports), then maybe we can figure out the default port
150 + netw, host, port, err := caddy.SplitNetworkAddress(upstream.Dial)
151 + if err != nil && port == "" && !strings.Contains(netw, "unix") {
152 + if host == "" {
153 + // assume all that was given was the host, no port
154 + host = upstream.Dial
155 + }
156 + // a port was not specified, but we may be able to
157 + // infer it if we know the standard ports on which
158 + // the transport protocol operates
159 + if ht, ok := h.Transport.(*HTTPTransport); ok {
160 + defaultPort := "80"
161 + if ht.TLS != nil {
162 + defaultPort = "443"
163 + }
164 + upstream.Dial = caddy.JoinNetworkAddress(netw, host, defaultPort)
165 + }
166 + }
167 +
168 // upstreams are allowed to map to only a single host,
169 // but an upstream's address may semantically represent
170 // multiple addresses, so make sure to handle each
@@ -474,7 +494,19 @@ func (h Handler) tryAgain(start time.Time, proxyErr error) bool {
494 // given upstream host. It must modify ONLY the request URL.
495 func (h Handler) directRequest(req *http.Request, upstream *Upstream) {
496 if req.URL.Host == "" {
477 - req.URL.Host = upstream.dialInfo.Address
497 + // we need a host, so set the upstream's host address
498 + fullHost := upstream.dialInfo.Address
499 +
500 + // but if the port matches the scheme, strip the port because
501 + // it's weird to make a request like http://example.com:80/.
502 + host, port, err := net.SplitHostPort(fullHost)
503 + if err == nil &&
504 + (req.URL.Scheme == "http" && port == "80") ||
505 + (req.URL.Scheme == "https" && port == "443") {
506 + fullHost = host
507 + }
508 +
509 + req.URL.Host = fullHost
510 }
511 }
512