Skip to content

Commit

Permalink
feat: add validator for IPv4 bind address / host:port
Browse files Browse the repository at this point in the history
supporting older Golang versions by using net.ParseIP, not netip.ParseAddr
  • Loading branch information
rtomadpg committed Jun 17, 2024
1 parent a947377 commit e022a95
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
24 changes: 24 additions & 0 deletions baked_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ var (
"ipv4": isIPv4,
"ipv6": isIPv6,
"ip": isIP,
"ipv4_port": isIPv4Port,
"cidrv4": isCIDRv4,
"cidrv6": isCIDRv6,
"cidr": isCIDR,
Expand Down Expand Up @@ -2704,6 +2705,29 @@ func isHostnamePort(fl FieldLevel) bool {
return true
}

// isIPv4Port validates a <ipv4>:<port> combination for fields typically used for socket address.
func isIPv4Port(fl FieldLevel) bool {
val := fl.Field().String()
ip, port, err := net.SplitHostPort(val)
if err != nil {
return false
}
// Port must be a iny <= 65535.
if portNum, err := strconv.ParseInt(
port, 10, 32,
); err != nil || portNum > 65535 || portNum < 1 {
return false
}

// If IP address is specified, it should match a valid IPv4 address
if ip != "" {
// we need to support older Golang versions, so we can not use netip.ParseAddr
parsedIp := net.ParseIP(ip)
return parsedIp != nil && parsedIp.To4() != nil
}
return true
}

// isLowercase is the validation function for validating if the current field's value is a lowercase string.
func isLowercase(fl FieldLevel) bool {
field := fl.Field()
Expand Down
32 changes: 32 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12377,6 +12377,38 @@ func Test_hostnameport_validator(t *testing.T) {
}
}

func Test_ipv4_port_validator(t *testing.T) {
type IPv4Port struct {
BindAddr string `validate:"ipv4_port"`
}

type testInput struct {
data string
expected bool
}
testData := []testInput{
{"192.168.1.1:1234", true},
{":1234", true},
{"localhost:1234", false},
{"aaa.bbb.ccc.ddd:234", false},
{":alpha", false},
{"1.2.3.4", false},
{"2001:db8::1:0.0.0.0:234", false},
{"2001:db8::1:0.0.0.0", false},
{"2001:db8::1:0.0.0.0:", false},
{"2001:db8::1:0.0.0.0:123456", false},
{"2001:db8::1:0.0.0.0:123456:", false},
}
for _, td := range testData {
h := IPv4Port{BindAddr: td.data}
v := New()
err := v.Struct(h)
if td.expected != (err == nil) {
t.Fatalf("Test failed for data: %v Error: %v", td.data, err)
}
}
}

func TestLowercaseValidation(t *testing.T) {
tests := []struct {
param string
Expand Down

0 comments on commit e022a95

Please sign in to comment.