final class UrlValidator

Validates URLs against a configurable policy: scheme, port, host allow/blocklist, userinfo, and resolved IP ranges. Used to guard server-side URL fetches against SSRF — set the policy to match your threat model.

Constants

private SchemePorts

Implicit ports for known schemes (used when URL has no explicit port).

Methods

__construct(array $schemes = ['https'], array|null $ports = [443], bool $allowPrivateIps = false, bool $allowLoopback = false, bool $allowLinkLocal = false, bool $allowReserved = false, bool $allowUserinfo = false, array|null $hostAllowlist = null, array|null $hostBlocklist = null)

Host patterns: exact ('example.com') or wildcard subdomain ('*.example.com' matches any depth but NOT apex; for apex list both forms). Multicast addresses are always rejected — never opt-in.

bool
allows(UrlImmutable|null $url)

Returns true if URL passes the entire policy: parseable, allowed scheme/port, userinfo policy, host allow/blocklist, and (for hostname hosts) every DNS-resolved A/AAAA address passes the IP-range policy. DNS lookup is skipped when host is an IP literal. Null URL returns false.

bool
allowsWithoutDns(UrlImmutable|null $url)

Same as allows() without DNS resolution and IP-range checks. Useful as a fast pre-filter, or when DNS validation is delegated to the fetch layer (e.g. CURLOPT_RESOLVE).

array
getResolvedIPs(UrlImmutable|null $url)

Returns DNS-resolved IPs that passed the full policy, or [] on any failure.

Details

at line 35
__construct(array $schemes = ['https'], array|null $ports = [443], bool $allowPrivateIps = false, bool $allowLoopback = false, bool $allowLinkLocal = false, bool $allowReserved = false, bool $allowUserinfo = false, array|null $hostAllowlist = null, array|null $hostBlocklist = null)

Host patterns: exact ('example.com') or wildcard subdomain ('*.example.com' matches any depth but NOT apex; for apex list both forms). Multicast addresses are always rejected — never opt-in.

Parameters

array $schemes

allowed schemes; empty array rejects all

array|null $ports

allowed ports, null = any; implicit port from scheme (https→443, http→80) is honored

bool $allowPrivateIps
bool $allowLoopback
bool $allowLinkLocal
bool $allowReserved
bool $allowUserinfo
array|null $hostAllowlist

if set, host must match one pattern; null = no allowlist; [] = reject all

array|null $hostBlocklist

if set, host must not match any pattern

at line 55
bool allows(UrlImmutable|null $url)

Returns true if URL passes the entire policy: parseable, allowed scheme/port, userinfo policy, host allow/blocklist, and (for hostname hosts) every DNS-resolved A/AAAA address passes the IP-range policy. DNS lookup is skipped when host is an IP literal. Null URL returns false.

Parameters

UrlImmutable|null $url

Return Value

bool

at line 66
bool allowsWithoutDns(UrlImmutable|null $url)

Same as allows() without DNS resolution and IP-range checks. Useful as a fast pre-filter, or when DNS validation is delegated to the fetch layer (e.g. CURLOPT_RESOLVE).

Parameters

UrlImmutable|null $url

Return Value

bool

at line 79
array getResolvedIPs(UrlImmutable|null $url)

Returns DNS-resolved IPs that passed the full policy, or [] on any failure.

Pass returned IPs to your HTTP client's connection pinning (CURLOPT_RESOLVE) to bind the actual fetch to validated addresses, defeating DNS rebinding race.

Parameters

UrlImmutable|null $url

Return Value

array

A records first, then AAAA, in dotted-quad / RFC 5952 form