Skip to content

Commit 8e7efe2

Browse files
committed
Implement config URL sanitization, add test
1 parent 8d211be commit 8e7efe2

File tree

3 files changed

+107
-11
lines changed

3 files changed

+107
-11
lines changed

configs/benchmark.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,26 +65,32 @@ type Benchmark struct {
6565
Network string `mapstructure:"network"`
6666
}
6767

68-
func (b Benchmark) Validate() (bool, error) {
68+
func (b *Benchmark) Validate() (bool, error) {
6969
if b.Consensus.Metrics.Peers.Enabled ||
7070
b.Consensus.Metrics.Attestation.Enabled ||
7171
b.Consensus.Metrics.Client.Enabled ||
7272
b.Consensus.Metrics.Latency.Enabled {
73-
if err := validateURL(b.Consensus.Address); err != nil {
73+
url, err := sanitizeURL(b.Consensus.Address)
74+
if err != nil {
7475
return false, errors.Join(err, errors.New("consensus client address was not a valid URL"))
7576
}
77+
b.Consensus.Address = url
7678
}
7779

7880
if b.Execution.Metrics.Peers.Enabled {
79-
if err := validateURL(b.Execution.Address); err != nil {
81+
url, err := sanitizeURL(b.Execution.Address)
82+
if err != nil {
8083
return false, errors.Join(err, errors.New("execution client address was not a valid URL"))
8184
}
85+
b.Execution.Address = url
8286
}
8387

8488
if b.SSV.Metrics.Peers.Enabled || b.SSV.Metrics.Connections.Enabled {
85-
if err := validateURL(b.SSV.Address); err != nil {
89+
url, err := sanitizeURL(b.SSV.Address)
90+
if err != nil {
8691
return false, errors.Join(err, errors.New("SSV client address was not a valid URL"))
8792
}
93+
b.SSV.Address = url
8894
}
8995

9096
network := network.Name(b.Network)

configs/config.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package configs
22

33
import (
44
"errors"
5+
"fmt"
56
"net/url"
67
)
78

@@ -12,19 +13,22 @@ type Config struct {
1213
Analyzer Analyzer `mapstructure:"analyzer"`
1314
}
1415

15-
func validateURL(str string) error {
16+
func sanitizeURL(str string) (string, error) {
1617
parsedURL, err := url.Parse(str)
1718
if err != nil {
18-
return err
19+
return "", err
1920
}
20-
21+
var validationErr error
2122
if parsedURL.Scheme == "" {
22-
return errors.New("scheme was empty")
23+
validationErr = errors.Join(validationErr, errors.New("scheme was empty"))
2324
}
24-
2525
if parsedURL.Host == "" {
26-
return errors.New("host was empty")
26+
validationErr = errors.Join(validationErr, errors.New("host was empty"))
27+
}
28+
29+
if validationErr != nil {
30+
return "", validationErr
2731
}
2832

29-
return nil
33+
return fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host), nil
3034
}

configs/config_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package configs
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
func TestSanitizeURL(t *testing.T) {
9+
tests := []struct {
10+
name, input, want, errMsg string
11+
wantErr bool
12+
}{
13+
{
14+
name: "Valid URL with http",
15+
input: "http://example.com/path?query=123",
16+
want: "http://example.com",
17+
wantErr: false,
18+
},
19+
{
20+
name: "Valid URL with https",
21+
input: "https://example.com",
22+
want: "https://example.com",
23+
wantErr: false,
24+
},
25+
{
26+
name: "URL with no scheme",
27+
input: "example.com",
28+
want: "",
29+
wantErr: true,
30+
errMsg: "scheme was empty",
31+
},
32+
{
33+
name: "URL with no scheme",
34+
input: "http://example.com/",
35+
want: "http://example.com",
36+
wantErr: false,
37+
},
38+
{
39+
name: "URL with no host",
40+
input: "http://",
41+
want: "",
42+
wantErr: true,
43+
errMsg: "host was empty",
44+
},
45+
{
46+
name: "Invalid URL format",
47+
input: "://example.com",
48+
want: "",
49+
wantErr: true,
50+
errMsg: "missing protocol scheme",
51+
},
52+
{
53+
name: "URL with user info",
54+
input: "https://user:pass@example.com",
55+
want: "https://example.com",
56+
wantErr: false,
57+
},
58+
{
59+
name: "Empty URL",
60+
input: "",
61+
want: "",
62+
wantErr: true,
63+
errMsg: "scheme was empty",
64+
},
65+
}
66+
67+
for _, tt := range tests {
68+
t.Run(tt.name, func(t *testing.T) {
69+
got, err := sanitizeURL(tt.input)
70+
if (err != nil) != tt.wantErr {
71+
t.Errorf("sanitizeURL() error = %v, wantErr %v", err, tt.wantErr)
72+
return
73+
}
74+
75+
if tt.wantErr && err != nil {
76+
if !strings.Contains(err.Error(), tt.errMsg) {
77+
t.Errorf("actual error = '%v', wantErrMsg: '%v'", err, tt.errMsg)
78+
}
79+
}
80+
81+
if got != tt.want {
82+
t.Errorf("sanitizeURL() URL got = %v, want %v", got, tt.want)
83+
}
84+
})
85+
}
86+
}

0 commit comments

Comments
 (0)