diff --git a/README.md b/README.md index 5182561..be985a9 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ This package currently provides the following checkers: - [alphanumeric](doc/checkers/alphanumeric.md) checks if the given string consists of only alphanumeric characters. - [ascii](doc/checkers/ascii.md) checks if the given string consists of only ASCII characters. - [digits](doc/checkers/digits.md) checks if the given string consists of only digit characters. +- [ip](doc/checkers/ip.md) checks if the given value is an IP address. - [ipv4](doc/checkers/ipv4.md) checks if the given value is an IPv4 address. - [ipv6](doc/checkers/ipv6.md) checks if the given value is an IPv6 address. - [max](doc/checkers/max.md) checks if the given value is less than the given maximum. diff --git a/checker.go b/checker.go index d450830..ca4bcd9 100644 --- a/checker.go +++ b/checker.go @@ -34,6 +34,7 @@ var makers = map[string]MakeFunc{ CheckerAlphanumeric: makeAlphanumeric, CheckerAscii: makeAscii, CheckerDigits: makeDigits, + CheckerIp: makeIp, CheckerIpV4: makeIpV4, CheckerIpV6: makeIpV6, CheckerMax: makeMax, diff --git a/doc/checkers/ip.md b/doc/checkers/ip.md new file mode 100644 index 0000000..58d4af2 --- /dev/null +++ b/doc/checkers/ip.md @@ -0,0 +1,28 @@ +# IP Checker + +The ```ip``` checker checks if the value is an IP address. If the value is not an IP address, the checker will return the ```NOT_IP``` result. Here is an example: + +```golang +type Request struct { + RemoteIp string `checkers:"ip"` +} + +request := &Request{ + RemoteIp: "192.168.1.1", +} + +_, valid := Check(request) +if !valid { + // Send the mistakes back to the user +} +``` + +In your custom checkers, you can call the ```ip``` checker function ```IsIp``` to validate the user input. Here is an example: + +```golang +result := IsIp("2001:db8::68") + +if result != ResultValid { + // Send the mistakes back to the user +} +``` diff --git a/doc/checkers/ipv4.md b/doc/checkers/ipv4.md index e7149e7..ee7ac0e 100644 --- a/doc/checkers/ipv4.md +++ b/doc/checkers/ipv4.md @@ -1,4 +1,4 @@ -# IpV4 Checker +# IPv4 Checker The ```ipv4``` checker checks if the value is an IPv4 address. If the value is not an IPv4 address, the checker will return the ```NOT_IP_V4``` result. Here is an example: diff --git a/doc/checkers/ipv6.md b/doc/checkers/ipv6.md index e5e7ed5..e2801ae 100644 --- a/doc/checkers/ipv6.md +++ b/doc/checkers/ipv6.md @@ -1,4 +1,4 @@ -# IpV4 Checker +# IPv6 Checker The ```ipv6``` checker checks if the value is an IPv6 address. If the value is not an IPv6 address, the checker will return the ```NOT_IP_V6``` result. Here is an example: diff --git a/ip.go b/ip.go new file mode 100644 index 0000000..c9bd10e --- /dev/null +++ b/ip.go @@ -0,0 +1,36 @@ +package checker + +import ( + "net" + "reflect" +) + +// CheckerIp is the name of the checker. +const CheckerIp = "ip" + +// ResultNotIp indicates that the given value is not an IP address. +const ResultNotIp = "NOT_IP" + +// IsIp checks if the given value is an IP address. +func IsIp(value string) Result { + ip := net.ParseIP(value) + if ip == nil { + return ResultNotIp + } + + return ResultValid +} + +// makeIp makes a checker function for the ip checker. +func makeIp(_ string) CheckFunc { + return checkIp +} + +// checkIp checks if the given value is an IP address. +func checkIp(value, _ reflect.Value) Result { + if value.Kind() != reflect.String { + panic("string expected") + } + + return IsIp(value.String()) +} diff --git a/ip_test.go b/ip_test.go new file mode 100644 index 0000000..1fd607b --- /dev/null +++ b/ip_test.go @@ -0,0 +1,57 @@ +package checker + +import "testing" + +func TestIsIpInvalid(t *testing.T) { + if IsIp("900.800.200.100") == ResultValid { + t.Fail() + } +} + +func TestIsIpValid(t *testing.T) { + if IsIp("2001:db8::68") != ResultValid { + t.Fail() + } +} + +func TestCheckIpNonString(t *testing.T) { + defer FailIfNoPanic(t) + + type Request struct { + RemoteIp int `checkers:"ip"` + } + + request := &Request{} + + Check(request) +} + +func TestCheckIpInvalid(t *testing.T) { + type Request struct { + RemoteIp string `checkers:"ip"` + } + + request := &Request{ + RemoteIp: "900.800.200.100", + } + + _, valid := Check(request) + if valid { + t.Fail() + } +} + +func TestCheckIpValid(t *testing.T) { + type Request struct { + RemoteIp string `checkers:"ip"` + } + + request := &Request{ + RemoteIp: "192.168.1.1", + } + + _, valid := Check(request) + if !valid { + t.Fail() + } +}