Standard library · The web
web/url
Imported as import "web/url" as url, its names are then url.…. Every signature below is the one the checker infers.
URLs taken apart and put together (RFC 3986): the scheme, who, the host, the port, the path, the query, the fragment; a query as pairs; a relative reference resolved against a base; percent-encoding both ways.
A Url is a record; text writes it back, and a part that was not there is empty (port is -1). Nothing is decoded on the way in — the path and query are as they were written — so decode what you look at.
u = url.parse("https://user@example.com:8443/a/b?x=1&y=two#top") |> unwrap_or(url.Url("", "", "", -1, "", "", "")) u.host # => example.com u.port # => 8443 u.path # => /a/b url.query_pairs("x=1&y=two%20words") # => Cons((x, 1), Cons((y, two words), Nil)) url.resolve("https://example.com/a/b/c", "../d?q") # => https://example.com/a/d?q url.encode("a b&c") # => a%20b%26c
Types
Url
Url(scheme: Str, user: Str, host: Str, port: Int, path: Str, query: Str, fragment: Str)
Functions
fn parse(s: Str) -> Option(Url)
A URL with a scheme and //, or None. A path-only reference is not a URL; resolve it against one.
url.parse("http://h/p?q#f") # => Some(url.Url(http, , h, -1, /p, q, f)) url.parse("/just/a/path") # => None
fn text(u: Url) -> Str
url.text(url.Url("https", "me", "h.io", 8080, "/x", "a=1", "top")) # => https://me@h.io:8080/x?a=1#top
fn port_of(u: Url) -> Int
The port, or the scheme's usual one: 80, 443, 21, 22, 25.
url.port_of(url.parse("https://h/") |> unwrap_or(url.Url("", "", "", -1, "", "", ""))) # => 443 url.port_of(url.parse("http://h:81/") |> unwrap_or(url.Url("", "", "", -1, "", "", ""))) # => 81
fn origin(u: Url) -> Str
The scheme, host and port alone: https://example.com:8443.
url.origin(url.parse("https://example.com:8443/a?b") |> unwrap_or(url.Url("", "", "", -1, "", "", ""))) # => https://example.com:8443
fn query_pairs(query: Str) -> List((Str, Str))
a=1&b=two%20words as decoded pairs; a key without = has the value "".
url.query_pairs("a=1&b=two%20words&flag") # => Cons((a, 1), Cons((b, two words), Cons((flag, ), Nil)))
fn query_text(pairs: List((Str, Str))) -> Str
The pairs as a query, each side encoded.
url.query_text(Cons(("q", "a b"), Cons(("n", "1"), Nil))) # => q=a%20b&n=1
fn query_get(query: Str, name: Str) -> Option(Str)
The first value under name, decoded.
url.query_get("a=1&b=2&a=3", "a") # => Some(1) url.query_get("a=1", "z") # => None
fn encode(s: Str) -> Str
Percent-encoding of everything but the unreserved characters — letters, digits, - . _ ~ — so the result is safe anywhere in a URL.
url.encode("a b/c~d") # => a%20b%2Fc~d
fn decode(s: Str) -> Str
%xx back to bytes and + to a space, as a form sends them; a % not followed by two hex digits is kept as it is.
url.decode("a%20b+c") # => a b c url.decode("100%") # => 100%
fn resolve(base: Str, reference: Str) -> Str
reference seen from base, as a browser follows a link: absolute references stand; //host/x keeps the scheme; /x keeps the host; x, ./x and ../x are joined to the base's path with the dots resolved; ?q and #f alone replace only that part.
url.resolve("https://example.com/a/b/c", "../d") # => https://example.com/a/d url.resolve("https://example.com/a/b/c", "/x") # => https://example.com/x url.resolve("https://example.com/a/b/c", "//other/y") # => https://other/y url.resolve("https://example.com/a/b/c", "?q=1") # => https://example.com/a/b/c?q=1 url.resolve("https://example.com/a", "http://else/") # => http://else/
Tests
test_parse_the_partstest_what_is_not_a_urltest_query_and_encodingtest_resolve_like_a_browser