Add support for parsing IPs by version (IPv4 and IPv6) with validation logic
This commit is contained in:
@@ -11,14 +11,25 @@ import (
|
|||||||
type Parser interface {
|
type Parser interface {
|
||||||
// Parse reads the body and returns a slice of IP addresses.
|
// Parse reads the body and returns a slice of IP addresses.
|
||||||
Parse(body io.Reader, validator IPValidator, limit uint) (IPs, error)
|
Parse(body io.Reader, validator IPValidator, limit uint) (IPs, error)
|
||||||
|
|
||||||
|
ParseIPsByVersion(body io.Reader, validator IPValidator, limit uint) (ipV4 IPs, ipV6 IPs, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPValidator interface defines the contract for validating IP addresses.
|
// IPValidator interface defines the contract for validating IP addresses.
|
||||||
type IPValidator interface {
|
type IPValidator interface {
|
||||||
// IsValid checks if the given IP address is valid.
|
// IsValid checks if the given IP address is valid.
|
||||||
IsValid(ip string) bool
|
IsValid(ip string) bool
|
||||||
|
|
||||||
|
IsValidAndReturnVersion(ip string) (bool, IPVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IPVersion int
|
||||||
|
|
||||||
|
const (
|
||||||
|
IPVersion4 IPVersion = iota
|
||||||
|
IPVersion6
|
||||||
|
)
|
||||||
|
|
||||||
// IPs is a slice of IP addresses.
|
// IPs is a slice of IP addresses.
|
||||||
type IPs []string
|
type IPs []string
|
||||||
|
|
||||||
@@ -50,6 +61,48 @@ func (v *DefaultIPValidator) IsValid(value string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsValidAndReturnVersion checks if the given IP address is valid and returns the IP version.
|
||||||
|
// It returns true if the IP address is not a loopback address and the IP version is either IPv4 or IPv6.
|
||||||
|
func (v *DefaultIPValidator) IsValidAndReturnVersion(value string) (bool, IPVersion) {
|
||||||
|
if value == "" {
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip := net.ParseIP(value); ip != nil {
|
||||||
|
if ip.IsLoopback() {
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip.To4() != nil {
|
||||||
|
return true, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip.To16() != nil {
|
||||||
|
return true, IPVersion6
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip, _, err := net.ParseCIDR(value); err == nil {
|
||||||
|
if ip.IsLoopback() {
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip.To4() != nil {
|
||||||
|
return true, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip.To16() != nil {
|
||||||
|
return true, IPVersion6
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
// IPRangeValidator implements IPValidator interface.
|
// IPRangeValidator implements IPValidator interface.
|
||||||
// It validates IP ranges by parsing them using net.ParseIP and checking if the start and end IPs are in the same network.
|
// It validates IP ranges by parsing them using net.ParseIP and checking if the start and end IPs are in the same network.
|
||||||
type IPRangeValidator struct{}
|
type IPRangeValidator struct{}
|
||||||
@@ -89,3 +142,43 @@ func (v *IPRangeValidator) IsValid(value string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *IPRangeValidator) IsValidAndReturnVersion(value string) (bool, IPVersion) {
|
||||||
|
if value == "" {
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(value, "-")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
start := net.ParseIP(strings.TrimSpace(parts[0]))
|
||||||
|
end := net.ParseIP(strings.TrimSpace(parts[1]))
|
||||||
|
if start == nil || end == nil {
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
|
||||||
|
start4 := start.To4()
|
||||||
|
end4 := end.To4()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case start4 != nil && end4 != nil:
|
||||||
|
if bytes.Compare(start4, end4) <= 0 {
|
||||||
|
return true, IPVersion4
|
||||||
|
}
|
||||||
|
return false, IPVersion4
|
||||||
|
case start4 == nil && end4 == nil:
|
||||||
|
start16 := start.To16()
|
||||||
|
end16 := end.To16()
|
||||||
|
if start16 == nil || end16 == nil {
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
if bytes.Compare(start16, end16) <= 0 {
|
||||||
|
return true, IPVersion6
|
||||||
|
}
|
||||||
|
return false, IPVersion4
|
||||||
|
default:
|
||||||
|
return false, IPVersion4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user