std/uri/uri
std/uri/src/uri.trb
Uri and UriReference: RFC 3986, read and normalized at construction, with Equals, Hash and Compare over the
normalized form (docs/design/URI.md sections 3 to 5).
Both are capsules over one private record of the five parts, so the parser, the recomposition, the comparison and
the resolution are written once. A Uri has a scheme; a UriReference may be relative, and resolving it against a
Uri answers a Uri and cannot fail.
type Uri
type Uri with Show, Equals, Hash, Compare
A URI per RFC 3986 section 3: a scheme, and an authority, a path, a query and a fragment after it.
A Uri is a value, read from text with Uri.tryFrom and normalized on the way in - the scheme and a registered name
lower case, escapes upper case and decoded where they name an unreserved character, dot segments gone, every character
a URI cannot hold percent-encoded as UTF-8 - so ==, hash() and compare() are over the canonical form. What is
a guess about a scheme rather than a fact about URIs, a default port, is Uri.normalized's.
It is a capsule: its field is private and has no default, so Uri.tryFrom is the one way in and Uri.text the
way out, and the two are the conversion pair Encode and Decode go through - a URI in a JSON document is its text.
Examples
const uri: Uri = "HTTPS://Example.TEST/a/./b/../c?q=1#top"
print "{uri.scheme()} {uri.host()} {uri.path()}"
Pitfalls
show()hides a password (postgres://ada:***@host/db), andtext()is the whole text: the one a request, a file or an encoder needs.http://example.test:80/andhttp://example.test/are two values untilUri.normalizeddrops the default port.
Related
UriReference- a URI or a relative reference, andUriReference.resolvedto make aUriof one.Urn- aurn:URI read into its namespace and name.
fn scheme
fn scheme(): String
The scheme, lower case: https.
fn authority
fn authority(): Authority?
The authority, where the URI has one. None and an empty host are different things.
fn host
fn host(): Host?
The host of the authority, where there is one.
fn port
fn port(): Int?
The port that is written out. It is not the port the scheme defaults to: Uri.defaultPort is.
fn defaultPort
fn defaultPort(): Int?
The port the scheme defaults to, for the five schemes IANA fixes one for: http, https, ws, wss, ftp.
fn socketAddress
fn socketAddress(): SocketAddress?
Where to connect without a resolver: the host where it is an IP literal, with the written port or the scheme's
default. None for a registered name, which std/network resolves.
fn path
fn path(): String
The path. Always there, and "" where the URI has none.
fn segments
fn segments(): List<String>
The path split at its /, still percent-encoded, without the empty segment in front of an absolute path: / has
none, /a/b/ has a, b and "".
fn query
fn query(): String?
Everything between the first ? and the #, as RFC 3986 leaves it: one opaque string.
fn fragment
fn fragment(): String?
Everything after the first #.
fn isUrl
fn isUrl(): Bool
Whether the URI has an authority: the question a Url type would have been for.
fn isUrn
fn isUrn(): Bool
Whether the scheme is urn. Urn.tryFrom(uri) reads the parts of one.
fn queryParameters
fn queryParameters(): Map<String, List<String>>
The query read as application/x-www-form-urlencoded: every value of every name, in order.
fn queryParameter
fn queryParameter(name: String): String?
The first value of a query parameter, which is what almost every caller of Uri.queryParameters wants.
fn withQueryParameters
fn withQueryParameters(parameters: Map<String, List<String>>): Uri
The same URI with its query written from parameters, and with none where parameters is empty.
fn withFragment
fn withFragment(fragment: String?): Uri
The same URI with its fragment replaced by fragment, and with none where it is None. The text is written as it
is: every character a fragment cannot hold is percent-encoded, % among them.
fn joined
fn joined(relative: String): Uri
relative below this URI's path: split at /, each segment percent-encoded, . and empty segments dropped, and
.. removing only a segment relative itself added - so the answer is never above this URI's path, whatever
relative is. The query and the fragment belong to the old resource and are dropped.
Examples
const base: Uri = "https://example.test/users"
print base.joined("Ada Lovelace/posts")
fn normalized
fn normalized(): Uri
RFC 3986 section 6.2.3, scheme-based normalization: a port that is the scheme's default is dropped and an empty
path under an authority becomes /. It is a member and not part of construction, because the default port of a
scheme is a fact about five schemes and not a fact about URIs.
fn relativeTo
fn relativeTo(base: Uri): UriReference
This URI as seen from base: the shortest reference that UriReference.resolved turns back into this one. Where
the schemes differ it is the whole URI, and where the authorities differ it starts with //.
fn text
fn text(): String
The canonical text: the recomposition of RFC 3986 section 5.3, with every part of it. A password in the user information is in this text, and the name is what makes that greppable.
fn iriText
fn iriText(): String
The IRI this URI stands for (RFC 3987 section 3.2): every escape of a UTF-8 character outside ASCII decoded, every
A-label of the host shown as its U-label (https://münchen.test/ for https://xn--mnchen-3ya.test/), and everything
else as Uri.text has it, so Uri.tryFrom(uri.iriText()) is the same URI again. It carries the
password, as text() does.
fn show
fn show(): String
The canonical text with a password in the user information replaced by ***. Uri.text is the whole one.
fn compare
fn compare(other: Uri): Ordering
Scheme, then authority, then path, then query, then fragment, each None before every Some.
extend Uri with TryFrom<String, UriError>
extend Uri with TryFrom<String, UriError>
A text read as a URI and normalized on the way in.
Examples
print Uri.tryFrom("HTTP://Example.COM:80/a/./b/../c?q=1#top")
Errors
UriError.Relativefor a relative reference, whichUriReference.tryFromreads.UriError.InvalidScheme,UriError.InvalidEscape,UriError.InvalidHost,UriError.NonAsciiHostandUriError.InvalidPortfor a text that is no URI reference at all.
fn tryFrom
static fn tryFrom(value: String): Result<Uri, UriError>
extend String with From<Uri>
extend String with From<Uri>
The way back out, and with Uri.tryFrom the one conversion pair of the capsule. It is Uri.text and not
Uri.show, because this is the direction Encode is derived through, and a configuration that round trips without
its password is a configuration that stopped working.
fn from
static fn from(value: Uri): String
type UriReference
type UriReference with Show, Equals, Hash, Compare
A URI reference per RFC 3986 section 4.1: a Uri, or a relative reference - ../a, /b?c, //host/d, #top -
that means something only against a base. UriReference.resolved is that meaning, and it answers a Uri.
It is normalized as a Uri is, except that the dot segments of a relative path (../a) are kept: they mean
something only once a base is known.
Examples
const base: Uri = "https://example.test/guide/start.html"
const link: UriReference = "../reference/index.html#top"
print link.resolved(against: base)
Related
Uri- a reference with a scheme, andUri.relativeTofor the way back.
fn scheme
fn scheme(): String?
The scheme, lower case. None for a relative reference.
fn authority
fn authority(): Authority?
The authority, where the reference has one.
fn host
fn host(): Host?
The host of the authority, where there is one.
fn port
fn port(): Int?
The port that is written out.
fn path
fn path(): String
The path. Always there, and "" where the reference has none.
fn segments
fn segments(): List<String>
The path split at its /, still percent-encoded, without the empty segment in front of an absolute path.
fn query
fn query(): String?
Everything between the first ? and the #.
fn fragment
fn fragment(): String?
Everything after the first #.
fn isAbsolute
fn isAbsolute(): Bool
Whether the reference has a scheme. Its opposite is UriReference.isRelative.
fn isRelative
fn isRelative(): Bool
Whether the reference has no scheme, so that it means something only against a base.
fn uri
fn uri(): Uri?
The reference as a Uri, where it has a scheme.
fn resolved
fn resolved(against: Uri): Uri
This reference resolved against base, per RFC 3986 section 5.2 (the strict reading: a reference with a scheme is
itself). It cannot fail, because a Uri always has the scheme section 5.2.1 asks of a base.
fn queryParameters
fn queryParameters(): Map<String, List<String>>
The query read as application/x-www-form-urlencoded: every value of every name, in order.
fn queryParameter
fn queryParameter(name: String): String?
The first value of a query parameter.
fn withFragment
fn withFragment(fragment: String?): UriReference
The same reference with its fragment replaced by fragment, written as it is, and with none where it is None.
fn text
fn text(): String
The canonical text, with every part of it.
fn iriText
fn iriText(): String
The IRI this reference stands for (RFC 3987 section 3.2).
fn show
fn show(): String
The canonical text with a password in the user information replaced by ***.
fn compare
fn compare(other: UriReference): Ordering
Scheme, then authority, then path, then query, then fragment, each None before every Some.
extend UriReference with TryFrom<String, UriError>
extend UriReference with TryFrom<String, UriError>
A text read as a URI reference - a URI or a relative reference - and normalized on the way in.
Errors
UriError.InvalidSchemewhere the first segment of a relative path holds a:(1a:b), which RFC 3986 section 4.2 refuses because it would read as a scheme.UriError.InvalidEscape,UriError.InvalidHost,UriError.NonAsciiHostandUriError.InvalidPort.
fn tryFrom
static fn tryFrom(value: String): Result<UriReference, UriError>
extend UriReference with From<Uri>
extend UriReference with From<Uri>
Every URI is a reference. The way back is UriReference.uri, and deliberately not a TryFrom on Uri.
fn from
static fn from(value: Uri): UriReference
extend String with From<UriReference>
extend String with From<UriReference>
The way back out of UriReference, and with UriReference.tryFrom its conversion pair.
fn from
static fn from(value: UriReference): String
extend UriReference with TryFrom<Path, UriError>
extend UriReference with TryFrom<Path, UriError>
A Path written as a URI reference: an absolute path as a file: URI - the root becomes the authority or the first
segment - and a relative path as a relative reference. Every component is percent-encoded as UTF-8.
Errors
UriError.InvalidHostfor a UNC share whose server name IDNA refuses.
fn tryFrom
static fn tryFrom(value: Path): Result<UriReference, UriError>
extend Uri with TryFrom<Path, UriError>
extend Uri with TryFrom<Path, UriError>
A Path written as a file: URI.
Errors
UriError.Relativefor a relative path, which has nofile:URI.UriError.InvalidHostfor a UNC share whose server name IDNA refuses.
fn tryFrom
static fn tryFrom(value: Path): Result<Uri, UriError>
extend Path with TryFrom<Uri, UriError>
extend Path with TryFrom<Uri, UriError>
A file: URI read as a Path, in every form RFC 8089 and its appendices know: file:///x, file:/x,
file://localhost/x, file:///C:/x, file:///C|/x, file:C:/x and file://server/share/x. A fragment points into
the document and is ignored.
Errors
UriError.NotAFilefor a URI whose scheme is notfile, for a query, for an escape that names a separator and for a path that is not absolute.UriError.NotTextfor escapes whose bytes are not UTF-8.
fn tryFrom
static fn tryFrom(value: Uri): Result<Path, UriError>
extend Path with TryFrom<UriReference, UriError>
extend Path with TryFrom<UriReference, UriError>
A URI reference read as a Path: a file: URI as Path.tryFrom of a Uri reads it, and a relative-path reference
as the relative path it spells.
Errors
UriError.NotAFilefor another scheme, a network-path reference (//server/x), a query and an escape that names a separator.UriError.NotTextfor escapes whose bytes are not UTF-8.
fn tryFrom
static fn tryFrom(value: UriReference): Result<Path, UriError>