ipaddr

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 3 Imported by: 0

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

func IsValid(s string) bool

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

func Parse(s string) (*Address, error)

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) Kind

func (a *Address) Kind() string

Kind returns the address family: "ipv4" or "ipv6".

func (*Address) Match

func (a *Address) Match(cidr string) (bool, error)

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

func (a *Address) Range() string

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

func (*Address) String

func (a *Address) String() string

String returns the canonical textual representation of the address.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL