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

cmd: Clean up, simplify reverse proxy command; fix some edge cases

Now we take advantage of the address parsing capabilities of the HTTP caddyfile.

Matthew Holt committed Apr 27, 2020 at 15:53 UTC c11d0e47a3cfbfd0dc00999b6f7ed082ad274e1f
1 file changed +61 -36
modules/caddyhttp/reverseproxy/command.go
+61 -36
@@ -20,11 +20,11 @@ import (
20 "fmt"
21 "net"
22 "net/http"
23 - "net/url"
24 - "strings"
23 + "strconv"
24
25 "github.com/caddyserver/caddy/v2"
26 "github.com/caddyserver/caddy/v2/caddyconfig"
27 + "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
28 caddycmd "github.com/caddyserver/caddy/v2/cmd"
29 "github.com/caddyserver/caddy/v2/modules/caddyhttp"
30 "github.com/caddyserver/caddy/v2/modules/caddyhttp/headers"
@@ -40,10 +40,15 @@ func init() {
40 A simple but production-ready reverse proxy. Useful for quick deployments,
41 demos, and development.
42
43 -Simply shuttles HTTP traffic from the --from address to the --to address.
43 +Simply shuttles HTTP(S) traffic from the --from address to the --to address.
44
45 -If the --from address has a domain name, Caddy will attempt to serve the
46 -proxy over HTTPS with a certificate.
45 +Unless otherwise specified in the addresses, the --from address will be
46 +assumed to be HTTPS if a hostname is given, and the --to address will be
47 +assumed to be HTTP.
48 +
49 +If the --from address has a host or IP, Caddy will attempt to serve the
50 +proxy over HTTPS with a certificate (unless overridden by the HTTP scheme
51 +or port).
52
53 If --change-host-header is set, the Host header on the request will be modified
54 from its original incoming value to the address of the upstream. (Otherwise, by
@@ -51,7 +56,7 @@ default, all incoming headers are passed through unmodified.)
56 `,
57 Flags: func() *flag.FlagSet {
58 fs := flag.NewFlagSet("file-server", flag.ExitOnError)
54 - fs.String("from", "localhost:443", "Address on which to receive traffic")
59 + fs.String("from", "localhost", "Address on which to receive traffic")
60 fs.String("to", "", "Upstream address to which to to proxy traffic")
61 fs.Bool("change-host-header", false, "Set upstream Host header to address of upstream")
62 return fs
@@ -64,43 +69,69 @@ func cmdReverseProxy(fs caddycmd.Flags) (int, error) {
69 to := fs.String("to")
70 changeHost := fs.Bool("change-host-header")
71
67 - if from == "" {
68 - from = "localhost:443"
72 + httpPort := strconv.Itoa(caddyhttp.DefaultHTTPPort)
73 + httpsPort := strconv.Itoa(caddyhttp.DefaultHTTPSPort)
74 +
75 + if to == "" {
76 + return caddy.ExitCodeFailedStartup, fmt.Errorf("--to is required")
77 }
78
71 - // URLs need a scheme in order to parse successfully
72 - if !strings.Contains(from, "://") {
73 - from = "http://" + from
79 + // set up the downstream address; assume missing information from given parts
80 + fromAddr, err := httpcaddyfile.ParseAddress(from)
81 + if err != nil {
82 + return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid downstream address %s: %v", from, err)
83 + }
84 + if fromAddr.Path != "" {
85 + return caddy.ExitCodeFailedStartup, fmt.Errorf("paths are not allowed: %s", from)
86 }
75 - if !strings.Contains(to, "://") {
76 - to = "http://" + to
87 + if fromAddr.Scheme == "" {
88 + if fromAddr.Port == httpPort || fromAddr.Host == "" {
89 + fromAddr.Scheme = "http"
90 + } else {
91 + fromAddr.Scheme = "https"
92 + }
93 + }
94 + if fromAddr.Port == "" {
95 + if fromAddr.Scheme == "http" {
96 + fromAddr.Port = httpPort
97 + } else if fromAddr.Scheme == "https" {
98 + fromAddr.Port = httpsPort
99 + }
100 }
101
79 - fromURL, err := url.Parse(from)
102 + // set up the upstream address; assume missing information from given parts
103 + toAddr, err := httpcaddyfile.ParseAddress(to)
104 if err != nil {
81 - return caddy.ExitCodeFailedStartup, fmt.Errorf("parsing 'from' URL: %v", err)
105 + return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid upstream address %s: %v", to, err)
106 }
83 - toURL, err := url.Parse(to)
84 - if err != nil {
85 - return caddy.ExitCodeFailedStartup, fmt.Errorf("parsing 'to' URL: %v", err)
107 + if toAddr.Path != "" {
108 + return caddy.ExitCodeFailedStartup, fmt.Errorf("paths are not allowed: %s", to)
109 }
87 -
88 - if toURL.Port() == "" {
89 - toPort := "80"
90 - if toURL.Scheme == "https" {
91 - toPort = "443"
110 + if toAddr.Scheme == "" {
111 + if toAddr.Port == httpsPort {
112 + toAddr.Scheme = "https"
113 + } else {
114 + toAddr.Scheme = "http"
115 + }
116 + }
117 + if toAddr.Port == "" {
118 + if toAddr.Scheme == "http" {
119 + toAddr.Port = httpPort
120 + } else if toAddr.Scheme == "https" {
121 + toAddr.Port = httpsPort
122 }
93 - toURL.Host = net.JoinHostPort(toURL.Host, toPort)
123 }
124
125 + // proceed to build the handler and server
126 +
127 ht := HTTPTransport{}
97 - if toURL.Scheme == "https" {
128 + if toAddr.Scheme == "https" {
129 ht.TLS = new(TLSConfig)
130 }
131
132 handler := Handler{
133 TransportRaw: caddyconfig.JSONModuleObject(ht, "protocol", "http", nil),
103 - Upstreams: UpstreamPool{{Dial: toURL.Host}},
134 + Upstreams: UpstreamPool{{Dial: net.JoinHostPort(toAddr.Host, toAddr.Port)}},
135 }
136
137 if changeHost {
@@ -118,23 +149,17 @@ func cmdReverseProxy(fs caddycmd.Flags) (int, error) {
149 caddyconfig.JSONModuleObject(handler, "handler", "reverse_proxy", nil),
150 },
151 }
121 - urlHost := fromURL.Hostname()
122 - if urlHost != "" {
152 + if fromAddr.Host != "" {
153 route.MatcherSetsRaw = []caddy.ModuleMap{
154 {
125 - "host": caddyconfig.JSON(caddyhttp.MatchHost{urlHost}, nil),
155 + "host": caddyconfig.JSON(caddyhttp.MatchHost{fromAddr.Host}, nil),
156 },
157 }
158 }
159
130 - listen := ":443"
131 - if urlPort := fromURL.Port(); urlPort != "" {
132 - listen = ":" + urlPort
133 - }
134 -
160 server := &caddyhttp.Server{
161 Routes: caddyhttp.RouteList{route},
137 - Listen: []string{listen},
162 + Listen: []string{":" + fromAddr.Port},
163 }
164
165 httpApp := caddyhttp.App{
@@ -153,7 +178,7 @@ func cmdReverseProxy(fs caddycmd.Flags) (int, error) {
178 return caddy.ExitCodeFailedStartup, err
179 }
180
156 - fmt.Printf("Caddy 2 proxying from %s to %s\n", fromURL, toURL)
181 + fmt.Printf("Caddy proxying %s -> %s\n", fromAddr.String(), toAddr.String())
182
183 select {}
184 }