Skip to content

Commit c0e9e77

Browse files
authored
Merge branch 'master' into add-tests
2 parents 1661cfd + 55b3397 commit c0e9e77

4 files changed

Lines changed: 124 additions & 6 deletions

File tree

.github/SECURITY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ We'll need enough information to verify the bug and make a patch. To speed thing
4949

5050
Please DO NOT use containers, VMs, cloud instances or services, or any other complex infrastructure in your steps. Always prefer `curl -v` instead of web browsers.
5151

52-
We consider publicly-registered domain names to be public information. This necessary in order to maintain the integrity of certificate transparency, public DNS, and other public trust systems. Do not redact domain names from your reports. The actual content of your domain name affects Caddy's behavior, so we need the exact domain name(s) to reproduce with, or your report will be ignored.
52+
We consider publicly-registered domain names to be public information. This is necessary in order to maintain the integrity of certificate transparency, public DNS, and other public trust systems. Do not redact domain names from your reports. The actual content of your domain name affects Caddy's behavior, so we need the exact domain name(s) to reproduce with, or your report will be ignored.
5353

5454
It will speed things up if you suggest a working patch, such as a code diff, and explain why and how it works. Reports that are not actionable, do not contain enough information, are too pushy/demanding, or are not able to convince us that it is a viable and practical attack on the web server itself may be deferred to a later time or possibly ignored, depending on available resources. Priority will be given to credible, responsible reports that are constructive, specific, and actionable. (We get a lot of invalid reports.) Thank you for understanding.
5555

caddytest/integration/reverseproxy_test.go

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ func TestReverseProxyWithPlaceholderDialAddress(t *testing.T) {
199199
],
200200
"handle": [
201201
{
202-
202+
203203
"handler": "reverse_proxy",
204204
"upstreams": [
205205
{
@@ -293,7 +293,7 @@ func TestReverseProxyWithPlaceholderTCPDialAddress(t *testing.T) {
293293
],
294294
"handle": [
295295
{
296-
296+
297297
"handler": "reverse_proxy",
298298
"upstreams": [
299299
{
@@ -374,7 +374,7 @@ func TestReverseProxyHealthCheck(t *testing.T) {
374374
http://localhost:9080 {
375375
reverse_proxy {
376376
to localhost:2020
377-
377+
378378
health_uri /health
379379
health_port 2021
380380
health_interval 10ms
@@ -495,7 +495,7 @@ func TestReverseProxyHealthCheckUnixSocket(t *testing.T) {
495495
http://localhost:9080 {
496496
reverse_proxy {
497497
to unix/%s
498-
498+
499499
health_uri /health
500500
health_port 2021
501501
health_interval 2s
@@ -553,7 +553,7 @@ func TestReverseProxyHealthCheckUnixSocketWithoutPort(t *testing.T) {
553553
http://localhost:9080 {
554554
reverse_proxy {
555555
to unix/%s
556-
556+
557557
health_uri /health
558558
health_interval 2s
559559
health_timeout 5s
@@ -831,3 +831,65 @@ func TestReverseProxySNIPlaceHolder(t *testing.T) {
831831
tester.AssertResponse(req, 200, "example.com")
832832
}
833833
}
834+
835+
func TestWeightedRoundRobinSelectionValidation(t *testing.T) {
836+
configTemplate := `
837+
{
838+
"apps": {
839+
"http": {
840+
"servers": {
841+
"srv0": {
842+
"listen": [":18080"],
843+
"routes": [
844+
{
845+
"handle": [
846+
{
847+
"handler": "reverse_proxy",
848+
"load_balancing": {
849+
"selection_policy": {
850+
"policy": "weighted_round_robin",
851+
"weights": %s
852+
}
853+
},
854+
"upstreams": [
855+
{"dial": "localhost:18081"},
856+
{"dial": "localhost:18082"}
857+
]
858+
}
859+
]
860+
}
861+
]
862+
}
863+
}
864+
}
865+
}
866+
}`
867+
868+
tests := []struct {
869+
name string
870+
weights string
871+
errMsg string
872+
}{
873+
{
874+
name: "negative weight",
875+
weights: "[-1, 2]",
876+
errMsg: "weight of an upstream cannot be negative",
877+
},
878+
{
879+
name: "zero total weight",
880+
weights: "[0, 0]",
881+
errMsg: "requires at least one upstream with a positive weight",
882+
},
883+
}
884+
885+
for _, tc := range tests {
886+
t.Run(tc.name, func(t *testing.T) {
887+
caddytest.AssertLoadError(
888+
t,
889+
fmt.Sprintf(configTemplate, tc.weights),
890+
"json",
891+
tc.errMsg,
892+
)
893+
})
894+
}
895+
}

modules/caddyhttp/reverseproxy/selectionpolicies.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,19 @@ func (r *WeightedRoundRobinSelection) Provision(ctx caddy.Context) error {
127127
return nil
128128
}
129129

130+
// Validate ensures that r's configuration is valid
131+
func (r *WeightedRoundRobinSelection) Validate() error {
132+
if r.totalWeight <= 0 {
133+
return fmt.Errorf("weighted_round_robin requires at least one upstream with a positive weight")
134+
}
135+
for _, weight := range r.Weights {
136+
if weight < 0 {
137+
return fmt.Errorf("weight of an upstream cannot be negative")
138+
}
139+
}
140+
return nil
141+
}
142+
130143
// Select returns an available host, if any.
131144
func (r *WeightedRoundRobinSelection) Select(pool UpstreamPool, _ *http.Request, _ http.ResponseWriter) *Upstream {
132145
if len(pool) == 0 {
@@ -891,6 +904,7 @@ var (
891904
_ Selector = (*CookieHashSelection)(nil)
892905

893906
_ caddy.Validator = (*RandomChoiceSelection)(nil)
907+
_ caddy.Validator = (*WeightedRoundRobinSelection)(nil)
894908

895909
_ caddy.Provisioner = (*RandomChoiceSelection)(nil)
896910
_ caddy.Provisioner = (*WeightedRoundRobinSelection)(nil)

modules/caddyhttp/reverseproxy/selectionpolicies_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,48 @@ func TestWeightedRoundRobinPolicy(t *testing.T) {
131131
}
132132
}
133133

134+
func TestWeightedRoundRobinSelection_Validate(t *testing.T) {
135+
tests := []struct {
136+
name string
137+
weights []int
138+
wantErr bool
139+
}{
140+
{
141+
name: "Valid 0 2 1 case",
142+
weights: []int{0, 2, 1},
143+
wantErr: false,
144+
},
145+
{
146+
name: "Invalid 0 case (single)",
147+
weights: []int{0},
148+
wantErr: true,
149+
},
150+
{
151+
name: "Invalid 0 0 case (multiple)",
152+
weights: []int{0, 0},
153+
wantErr: true,
154+
},
155+
{
156+
name: "Valid weights",
157+
weights: []int{1, 1, 1},
158+
wantErr: false,
159+
},
160+
}
161+
162+
for _, tt := range tests {
163+
t.Run(tt.name, func(t *testing.T) {
164+
s := &WeightedRoundRobinSelection{
165+
Weights: tt.weights,
166+
}
167+
_ = s.Provision(caddy.Context{})
168+
err := s.Validate()
169+
if (err != nil) != tt.wantErr {
170+
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
171+
}
172+
})
173+
}
174+
}
175+
134176
func TestWeightedRoundRobinPolicyWithZeroWeight(t *testing.T) {
135177
pool := testPool()
136178
wrrPolicy := WeightedRoundRobinSelection{

0 commit comments

Comments
 (0)