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)