uri

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

README

uri

Resilient helpers for parsing, validating, and inspecting URLs and hostnames: scheme/protocol handling, IANA top-level-domain validation, local-network detection, and SSRF-safe public-IP classification.

Most functions are forgiving by design — they take a raw string, do their best, and return an empty string or false rather than an error when the input is malformed. The Validate* functions are the exception: they return a derp error describing exactly what was wrong.

Map for the impatient

  • URLsurl.go: ParseURL (a stricter url.Parse that requires an http/https scheme and a valid hostname), ValidateURL, IsValidURL.
  • Hostnameshostname.go: Hostname (strip everything down to the host), ValidateHostname (RFC 1035 lengths + IANA TLD check, with IP and local names exempted).
  • Scheme / protocolscheme.go, protocol.go: Scheme (no ://) vs Protocol (with ://); GuessSchemeForHostname / PrependProtocol pick http for local hosts and https for public ones.
  • Local-network detectionlocalhost.go, loopback.go: IsLocalHostname, IsLocalURL, IsLoopback.
  • Public-IP / SSRFpublic.go: IsPublicIP, NotPublicIP, IsPublicIPAddress.
  • TLDstld.go, init.go: IsValidTLD, ValidateTLD, RefreshTLDs; the IANA list is embedded from _iana.txt.

What matters here

  • IsPublicIP (public.go) and IsLocalHostname (localhost.go) are two different trust boundaries — don't substitute one for the other. IsLocalHostname answers "should this use http and skip TLS" (loopback, .local, RFC 1918, link-local, unspecified). IsPublicIP answers "is this safe to connect to" and is the SSRF gate — it rejects everything IsLocalHostname does plus the full IANA special-use registry (CGNAT, TEST-NETs, 6to4/NAT64 ranges that can embed a private IPv4, etc.) that the stdlib predicates miss. For an SSRF check, always use IsPublicIP on the resolved IP at connection time (e.g. in a net.Dialer.Control hook), never a hostname string check.

  • The cloud-metadata endpoint 169.254.169.254 is deliberately caught by the link-local case in both IsLocalHostname and IsPublicIP. It looks like an ordinary public-ish address but routes to instance credentials — the single most important SSRF target. Don't "simplify" the link-local branches away.

  • IsPublicIP works on the resolved net.IP, not on a string — and that's the point. A string like 0x7f.1 or 2130706433 is loopback once parsed, but a naive string check won't see it. Resolve first, classify second.

  • ValidateHostname exempts IP addresses and local names before applying DNS rules. 127.0.0.1 and friday.local are valid hostnames here even though they have no IANA TLD. Only after those exemptions does it enforce RFC 1035 label/length limits and require the final segment to be a real IANA TLD. If you change the ordering, you'll start rejecting valid loopback/local inputs.

  • The TLD list is embedded at build time and loaded once in init(). RefreshTLDs can re-fetch the live list from IANA at runtime, but it is best-effort: on any network/read error it logs via derp and silently keeps the embedded list. It also caps the download with io.LimitReader(…, 1<<20) — keep that cap if you touch it.

  • Paired Is… / Not… predicates are intentional, not redundant. NotLocalURL, NotPublicIP, NotValidTLD, etc. exist so callers read naturally at the call site (if uri.NotPublicIP(ip)). Each Not… is a one-line negation of its Is… twin — keep them in sync.

  • Hostname lower-cases and strips, it does not validate. It will happily return garbage from garbage. Run the result through ValidateHostname if the input is untrusted.

See also

  • benpate/derp — the error type returned by the Validate* functions.

Documentation

Overview

Package uri provides helpers for parsing, validating, and inspecting URLs and hostnames, including scheme/protocol handling, local-network detection, and IANA top-level-domain validation.

Index

Constants

View Source
const ProtocolHTTP = "http://"

ProtocolHTTP represents the "http://" protocol string (including the :// suffix)

View Source
const ProtocolHTTPS = "https://"

ProtocolHTTPS represents the "https://" protocol string (including the :// suffix)

View Source
const ProtocolSuffix = "://"

ProtocolSuffix represents the "://" suffix that follows the protocol name

View Source
const SchemeHTTP = "http"

SchemeHTTP represents the "http" network scheme (without the :// suffix)

View Source
const SchemeHTTPS = "https"

SchemeHTTPS represents the "https" network scheme (without the :// suffix)

Variables

This section is empty.

Functions

func GuessProtocolForHostname

func GuessProtocolForHostname(hostname string) string

GuessProtocolForHostname returns the correct protocol for a given hostname. Hosts on the public network always use HTTPS, and hosts on the local network always use HTTP.

func GuessSchemeForHostname

func GuessSchemeForHostname(hostname string) string

GuessSchemeForHostname returns the correct scheme for a given hostname. Hosts on the public network always use HTTPS, and hosts on the local network always use HTTP.

func Host

func Host(url string) string

Host returns the protocol and hostname

func Hostname

func Hostname(value string) string

Hostname returns ONLY the hostname, removing the protocol, port, path, and querystring from a hostname

func IsLocalHostname

func IsLocalHostname(hostname string) bool

IsLocalHostname returns TRUE if the hostname is a local domain — a loopback or mDNS/internal name, or any IP address that is not publicly routable.

func IsLocalURL

func IsLocalURL(url string) bool

IsLocalURL returns TRUE if the URL contains a local hostname

func IsLoopback

func IsLoopback(domain string) bool

IsLoopback returns TRUE if the provided domain is a loopback address. This matches loopback hostnames ("localhost", the RFC 6761 ".localhost" TLD, and common /etc/hosts aliases) as well as any loopback IP, which covers the whole 127.0.0.0/8 block, ::1, and aliases such as "::ffff:127.0.0.1".

func IsPublicIP added in v0.0.7

func IsPublicIP(ip net.IP) bool

IsPublicIP reports whether ip is a globally-routable public address that is safe to connect to. It returns FALSE for loopback, private, link-local (including the 169.254.169.254 cloud-metadata endpoint), unspecified, multicast, broadcast, carrier-grade NAT, and other special-use ranges.

Use this to defend against SSRF: validate the resolved IP at connection time (e.g. in a net.Dialer Control hook) before connecting to a user-supplied host.

func IsPublicIPAddress added in v0.0.7

func IsPublicIPAddress(value string) bool

IsPublicIPAddress reports whether the given string is a valid IP address that is also a public, safe-to-connect address. An unparseable value returns FALSE.

func IsSchemeValid

func IsSchemeValid(scheme string) bool

IsSchemeValid returns TRUE if the scheme is http or https

func IsValidHostname

func IsValidHostname(hostname string) bool

IsValidHostname returns TRUE if the provided value contains a valid hostname.

func IsValidIP4Address

func IsValidIP4Address(ip string) bool

IsValidIP4Address checks if the given string is a valid IPv4 address.

func IsValidIP6Address

func IsValidIP6Address(ip string) bool

IsValidIP6Address checks if the given string is a valid IPv6 address.

func IsValidIPAddress

func IsValidIPAddress(ip string) bool

IsValidIPAddress checks if the given string is a valid IP address (either IPv4 or IPv6).

func IsValidTLD

func IsValidTLD(tld string) bool

IsValidTLD returns TRUE if the provided "top level domain" is found in the IANA list.

func IsValidURL

func IsValidURL(uri string) bool

IsValidURL returns TRUE if the URL is valid

func NormalizeHost added in v0.1.1

func NormalizeHost(value string) string

NormalizeHost extracts the bare hostname from any URL-ish value, regardless of its shape: a bare hostname, a "host:port", a full "scheme://" URL, a value with userinfo ("user@host"), or a bracketed IPv6 literal ("[::1]:8080"). The result is lower-cased. Unlike Hostname, the result MAY contain colons, because an IPv6 address (e.g. "::1") is returned in its canonical, unbracketed form.

func NotLocalHostname

func NotLocalHostname(hostname string) bool

NotLocalHostname returns TRUE if the hostname is NOT a local domain

func NotLocalURL

func NotLocalURL(url string) bool

NotLocalURL returns TRUE if the URL does NOT contain a local hostname

func NotLoopback

func NotLoopback(domain string) bool

NotLoopback returns TRUE if the provided domain is NOT a loopback address (otherserver.com, 192.168.0.5)

func NotPublicIP added in v0.0.7

func NotPublicIP(ip net.IP) bool

NotPublicIP returns TRUE if ip is NOT a public, safe-to-connect address.

func NotPublicIPAddress added in v0.0.7

func NotPublicIPAddress(value string) bool

NotPublicIPAddress returns TRUE if the given string is NOT a public IP address.

func NotSchemeValid

func NotSchemeValid(scheme string) bool

NotSchemeValid returns TRUE if the scheme is NOT http or https

func NotValidHostname added in v0.0.3

func NotValidHostname(hostname string) bool

NotValidHostname returns TRUE if the provided value does NOT contain a valid hostname.

func NotValidIPAddress added in v0.0.3

func NotValidIPAddress(ip string) bool

NotValidIPAddress checks if the given string is NOT a valid IP address.

func NotValidTLD

func NotValidTLD(tld string) bool

NotValidTLD returns TRUE if the provided "top level domain" is NOT found in the IANA list.

func NotValidURL

func NotValidURL(uri string) bool

NotValidURL returns TRUE if the URL is NOT valid

func ParseURL

func ParseURL(uri string) (*url.URL, error)

ParseURL is a drop-in replacement for url.Parse that requires a valid hostname and http/https scheme.

func Path

func Path(uri string) string

Path returns just the path portion of a URL.

func PathAndQuery

func PathAndQuery(uri string) string

PathAndQuery returns the path and query portions of a URL

func PrependProtocol

func PrependProtocol(uri string) string

PrependProtocol adds the correct protocol to the beginning of a URL if needed.

func Protocol

func Protocol(uri string) string

Protocol returns the protocol portion of a URL. If the URL is not valid, then an empty string is returned.

func RefreshTLDs

func RefreshTLDs()

RefreshTLDs loads the most recent TLD list from the IANA website.

func Scheme

func Scheme(uri string) string

Scheme returns the scheme portion of a URL (without the "://" suffix), or an empty string if the URL cannot be parsed.

func ValidateHostname

func ValidateHostname(hostname string) error

ValidateHostname validates a hostname and returns an error describing any issues found.

func ValidateTLD

func ValidateTLD(tld string) error

ValidateTLD returns an error if the provided top-level domain is empty or is not found in the IANA list.

func ValidateURL

func ValidateURL(uri string) error

ValidateURL checks to see that a URL properly formatted, has a valid hostname, and uses http or https as the scheme.

Types

This section is empty.

Jump to

Keyboard shortcuts

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