Documentation
¶
Overview ¶
Package ipaddr provides parsing and classification of IPv4 and IPv6 addresses. It is a small Go port of a subset of the JavaScript "ipaddr.js" library, built entirely on top of the standard library net package so that no third-party dependency is required.
The ipaddr.js module is widely used in the Node ecosystem (notably by Express and proxy middleware) to answer questions such as "is this a valid address?", "which family is it?", "does it fall inside this CIDR block?" and "what kind of address is it — loopback, private, multicast, public unicast?". This port exists to answer the same questions in Go programs that need to reason about client addresses, trust proxies, or filter traffic, while keeping the small, object-oriented feel of the original API: Parse yields an *Address value whose methods (Kind, String, Match, Range) mirror the JavaScript instance methods.
Parsing delegates to net.ParseIP after trimming surrounding whitespace, so any textual form the standard library accepts is accepted here. The address family is decided by inspecting the parsed value: an address that has a 4-byte representation and whose input text contains no colon is classified as "ipv4", and everything else as "ipv6". That colon check is deliberate — it keeps IPv4-mapped IPv6 literals such as "::ffff:1.2.3.4" on the IPv6 side rather than silently narrowing them, and the original input string is retained so that String reflects the family the caller actually wrote. Match parses a CIDR with net.ParseCIDR and reports whether the address is contained in that network, which works uniformly for both IPv4 and IPv6 ranges.
Range classifies an address into a category name closely following ipaddr.js's special-range tables. For IPv4 the categories are "unspecified", "broadcast", "multicast", "linkLocal", "loopback", "private", "reserved" and "unicast", where "unicast" is the fallthrough for ordinary public addresses. For IPv6 the categories are "unspecified", "loopback", "multicast", "linkLocal", "uniqueLocal", "ipv4Mapped" and "unicast". The checks are applied in order and the first match wins, so, for example, the all-zeros address is reported as "unspecified" before the more general unicast fallthrough is reached.
Edge cases are handled explicitly. Parse returns an error for empty input and for anything net.ParseIP rejects (for example "999.999.999.999" or a bare "192.168.1"); IsValid is a thin boolean wrapper over Parse for callers that only need a yes/no answer. Match returns a non-nil error when the CIDR string is malformed rather than reporting a false negative. Compared with Node, this port intentionally covers only address parsing, validity, family detection, CIDR containment and range classification; it does not implement ipaddr.js features such as address arithmetic, subnet-mask/prefix conversion, the fromByteArray constructors, or the full set of narrowly scoped reserved sub-ranges, and its "unicast" bucket therefore absorbs a few blocks that ipaddr.js would name individually.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsValid ¶
IsValid reports whether s is a valid IPv4 or IPv6 address.
Example ¶
ExampleIsValid demonstrates the boolean validity helper. IsValid is a thin wrapper over Parse that reports only whether the string is a syntactically valid IPv4 or IPv6 address. A loopback IPv4 address is valid, an IPv6 literal is valid, but an octet above 255 is not, and plain non-address text is not. It never returns an error, making it convenient for guard clauses. Use Parse instead when you need the parsed value or the specific failure reason.
package main
import (
"fmt"
"github.com/malcolmston/express/ipaddr"
)
func main() {
fmt.Println(ipaddr.IsValid("127.0.0.1"))
fmt.Println(ipaddr.IsValid("::1"))
fmt.Println(ipaddr.IsValid("10.0.0.256"))
fmt.Println(ipaddr.IsValid("garbage"))
}
Output: true true false false
Types ¶
type Address ¶
type Address struct {
// contains filtered or unexported fields
}
Address represents a parsed IPv4 or IPv6 address.
func Parse ¶
Parse parses s as an IPv4 or IPv6 address and returns an *Address. It returns an error if s is not a valid IP address.
Example ¶
ExampleParse parses a textual IPv4 address into an *Address and inspects it. Parse trims surrounding whitespace and rejects anything net.ParseIP cannot read, returning an error in that case. The Kind method reports the detected family, either "ipv4" or "ipv6". The String method returns the canonical form of the address, preserving the IPv4 family rather than widening it to an IPv4-mapped IPv6 literal. Here a dotted-quad address is recognised as IPv4 and printed back in its original family.
package main
import (
"fmt"
"github.com/malcolmston/express/ipaddr"
)
func main() {
a, err := ipaddr.Parse("192.168.1.1")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(a.Kind())
fmt.Println(a.String())
}
Output: ipv4 192.168.1.1
func (*Address) Match ¶
Match reports whether the address is contained within the given CIDR range, for example "192.168.0.0/16" or "2001:db8::/32". It returns an error if the CIDR is invalid.
Example ¶
ExampleAddress_Match tests CIDR containment. Match parses the given CIDR block with net.ParseCIDR and reports whether the address falls inside that network. A malformed CIDR yields a non-nil error rather than a false negative. Here the address 192.168.5.5 is inside 192.168.0.0/16 but outside 10.0.0.0/8. The same method works uniformly for IPv6 ranges. This mirrors the match method of the ipaddr.js library.
package main
import (
"fmt"
"github.com/malcolmston/express/ipaddr"
)
func main() {
a, _ := ipaddr.Parse("192.168.5.5")
in, _ := a.Match("192.168.0.0/16")
out, _ := a.Match("10.0.0.0/8")
fmt.Println(in)
fmt.Println(out)
}
Output: true false
func (*Address) Range ¶
Range classifies the address, returning a category name.
For IPv4 addresses the categories are: "unspecified", "broadcast", "multicast", "linkLocal", "loopback", "private", "reserved", and "unicast" (the default for ordinary public addresses).
For IPv6 addresses the categories are: "unspecified", "loopback", "multicast", "linkLocal", "uniqueLocal", "ipv4Mapped", and "unicast".
Example ¶
ExampleAddress_Range classifies addresses into category names. Range applies the special-range tables from ipaddr.js in order and returns the first match. A 10.x address is "private", a public address such as 8.8.8.8 is "unicast", and the IPv6 loopback ::1 is "loopback". IPv4 and IPv6 use overlapping but distinct category sets, with "unicast" as the fallthrough for ordinary public addresses. This is useful for deciding whether to trust or filter an address.
package main
import (
"fmt"
"github.com/malcolmston/express/ipaddr"
)
func main() {
for _, s := range []string{"10.1.2.3", "8.8.8.8", "::1"} {
a, _ := ipaddr.Parse(s)
fmt.Printf("%s -> %s\n", s, a.Range())
}
}
Output: 10.1.2.3 -> private 8.8.8.8 -> unicast ::1 -> loopback