@marcel91200 / caddy Mirror · read-only / commits / 6722426f
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: allow no port for SRV; fix regression in d55d50b (#3756)

* reverseproxy: fix breakage in handling SRV lookup introduced by 3695 * reverseproxy: validate against incompatible config options with lookup_srv * reverseproxy: add integration test cases for validations involving lookup_srv * reverseproxy: clarify the reason for skipping an iteration * grammar.. Oxford comma Co-authored-by: Francis Lavoie <lavofr@gmail.com> Co-authored-by: Francis Lavoie <lavofr@gmail.com> Fixes #3753

Mohammed Al Sahaf committed Oct 1, 2020 at 23:05 UTC 6722426f1a9e6c8a5fb0bbcafd4b5f99cad2b070
2 files changed +128 -9
caddytest/integration/reverseproxy_test.go
+103
@@ -13,6 +13,109 @@ import (
13 "github.com/caddyserver/caddy/v2/caddytest"
14 )
15
16 +func TestSRVReverseProxy(t *testing.T) {
17 + tester := caddytest.NewTester(t)
18 + tester.InitServer(`
19 + {
20 + "apps": {
21 + "http": {
22 + "servers": {
23 + "srv0": {
24 + "listen": [
25 + ":8080"
26 + ],
27 + "routes": [
28 + {
29 + "handle": [
30 + {
31 + "handler": "reverse_proxy",
32 + "upstreams": [
33 + {
34 + "lookup_srv": "srv.host.service.consul"
35 + }
36 + ]
37 + }
38 + ]
39 + }
40 + ]
41 + }
42 + }
43 + }
44 + }
45 + }
46 + `, "json")
47 +}
48 +
49 +func TestSRVWithDial(t *testing.T) {
50 + caddytest.AssertLoadError(t, `
51 + {
52 + "apps": {
53 + "http": {
54 + "servers": {
55 + "srv0": {
56 + "listen": [
57 + ":8080"
58 + ],
59 + "routes": [
60 + {
61 + "handle": [
62 + {
63 + "handler": "reverse_proxy",
64 + "upstreams": [
65 + {
66 + "dial": "tcp/address.to.upstream:80",
67 + "lookup_srv": "srv.host.service.consul"
68 + }
69 + ]
70 + }
71 + ]
72 + }
73 + ]
74 + }
75 + }
76 + }
77 + }
78 + }
79 + `, "json", `upstream: specifying dial address is incompatible with lookup_srv: 0: {\"dial\": \"tcp/address.to.upstream:80\", \"lookup_srv\": \"srv.host.service.consul\"}`)
80 +}
81 +
82 +func TestSRVWithActiveHealthcheck(t *testing.T) {
83 + caddytest.AssertLoadError(t, `
84 + {
85 + "apps": {
86 + "http": {
87 + "servers": {
88 + "srv0": {
89 + "listen": [
90 + ":8080"
91 + ],
92 + "routes": [
93 + {
94 + "handle": [
95 + {
96 + "handler": "reverse_proxy",
97 + "health_checks": {
98 + "active": {
99 + "path": "/ok"
100 + }
101 + },
102 + "upstreams": [
103 + {
104 + "lookup_srv": "srv.host.service.consul"
105 + }
106 + ]
107 + }
108 + ]
109 + }
110 + ]
111 + }
112 + }
113 + }
114 + }
115 + }
116 + `, "json", `upstream: lookup_srv is incompatible with active health checks: 0: {\"dial\": \"\", \"lookup_srv\": \"srv.host.service.consul\"}`)
117 +}
118 +
119 func TestReverseProxyHealthCheck(t *testing.T) {
120 tester := caddytest.NewTester(t)
121 tester.InitServer(`
modules/caddyhttp/reverseproxy/reverseproxy.go
+25 -9
@@ -129,6 +129,21 @@ func (h *Handler) Provision(ctx caddy.Context) error {
129 h.ctx = ctx
130 h.logger = ctx.Logger(h)
131
132 + // get validation out of the way
133 + for i, v := range h.Upstreams {
134 + // Having LookupSRV non-empty conflicts with 2 other config parameters: active health checks, and upstream dial address.
135 + // Therefore if LookupSRV is empty, then there are no immediately apparent config conflicts, and the iteration can be skipped.
136 + if v.LookupSRV == "" {
137 + continue
138 + }
139 + if h.HealthChecks != nil && h.HealthChecks.Active != nil {
140 + return fmt.Errorf(`upstream: lookup_srv is incompatible with active health checks: %d: {"dial": %q, "lookup_srv": %q}`, i, v.Dial, v.LookupSRV)
141 + }
142 + if v.Dial != "" {
143 + return fmt.Errorf(`upstream: specifying dial address is incompatible with lookup_srv: %d: {"dial": %q, "lookup_srv": %q}`, i, v.Dial, v.LookupSRV)
144 + }
145 + }
146 +
147 // start by loading modules
148 if h.TransportRaw != nil {
149 mod, err := ctx.LoadModule(h, "TransportRaw")
@@ -204,17 +219,18 @@ func (h *Handler) Provision(ctx caddy.Context) error {
219
220 // set up upstreams
221 for _, upstream := range h.Upstreams {
207 - addr, err := caddy.ParseNetworkAddress(upstream.Dial)
208 - if err != nil {
209 - return err
210 - }
211 -
212 - if addr.PortRangeSize() != 1 {
213 - return fmt.Errorf("multiple addresses (upstream must map to only one address): %v", addr)
214 - }
222 + if upstream.LookupSRV == "" {
223 + addr, err := caddy.ParseNetworkAddress(upstream.Dial)
224 + if err != nil {
225 + return err
226 + }
227
216 - upstream.networkAddress = addr
228 + if addr.PortRangeSize() != 1 {
229 + return fmt.Errorf("multiple addresses (upstream must map to only one address): %v", addr)
230 + }
231
232 + upstream.networkAddress = addr
233 + }
234 // create or get the host representation for this upstream
235 var host Host = new(upstreamHost)
236 existingHost, loaded := hosts.LoadOrStore(upstream.String(), host)