URI
The URI component provides RFC 3986 compliant parsing, normalization, reference resolution, and RFC 6570 URI Template expansion.
Parsing
Parse any URI string into a structured, normalized URI object:
use Psl\IO;
use Psl\URI;
$uri = URI\parse('https://Example.COM:443/foo/../bar?q=1#frag');
// "https"
IO\write_line('%s', $uri->scheme ?? '<unknown>');
// "example.com" - lowercased
IO\write_line('%s', $uri->authority?->host?->toString() ?? '<unknown>');
// 443
IO\write_line('%d', $uri->authority->port ?? 0);
// "/bar" - dot segments removed
IO\write_line('%s', $uri->path);
// "q=1"
IO\write_line('%s', $uri->query ?? '<unknown>');
// "frag"
IO\write_line('%s', $uri->fragment ?? '<unknown>');
// "https://example.com:443/bar?q=1#frag"
IO\write_line('%s', $uri->toString());
Normalization is applied eagerly: scheme and host are lowercased, percent-encoding is normalized (unreserved characters decoded, hex digits uppercased), and dot segments (/../, /./) are removed.
Reference Resolution
Resolve relative references against a base URI per RFC 3986 Section 5:
use Psl\IO;
use Psl\URI;
$base = URI\parse('https://example.com/a/b/c');
// "https://example.com/a/d"
IO\write_line('%s', URI\resolve($base, URI\parse('../d'))->toString());
// "https://other/x"
IO\write_line('%s', URI\resolve($base, URI\parse('//other/x'))->toString());
// "https://example.com/a/b/c?q=1"
IO\write_line('%s', URI\resolve($base, URI\parse('?q=1'))->toString());
URI Templates
Parse and expand RFC 6570 URI Templates (Levels 1–4):
use Psl\IO;
use Psl\URI\Template;
$template = Template\parse('https://api.example.com/users/{id}/repos{?sort,page}');
$uri = $template->expand([
'id' => '42',
'sort' => 'stars',
'page' => '2',
]);
// "https://api.example.com/users/42/repos?sort=stars&page=2"
IO\write_line('%s', $uri->toString());
All operators are supported: simple {var}, reserved {+var}, fragment {#var}, label {.var}, path {/var}, parameter {;var}, query {?var}, and continuation {&var}. Modifiers include prefix {var:3} and explode {var*}.
Authority & Hosts
The authority component is structured into user info, host, and port. Hosts are typed - either an IP address or a registered name:
use Psl\IO;
use Psl\URI;
$uri = URI\parse('ssh://git@[::1%25eth0]:22/repo.git');
$authority = $uri->authority;
Psl\invariant($authority !== null, 'Invalid URI authority.');
// "git"
IO\write_line('%s', $authority->userInfo ?? '<unknown>');
// 22
IO\write_line('%d', $authority->port ?? 0);
// "[::1%25eth0]"
IO\write_line('%s', $authority->host->toString());
IPv6 addresses use RFC 5952 canonical form and support RFC 6874 zone identifiers.
Standards
| RFC | Title |
|---|---|
| RFC 3986 | Uniform Resource Identifier (URI): Generic Syntax |
| RFC 6570 | URI Template (Levels 1–4) |
| RFC 6874 | IPv6 Zone Identifiers in URIs |
| RFC 5952 | IPv6 Address Text Representation |
See src/Psl/URI/ for the full API.