A validated HTTP or HTTPS URL implemented entirely in Roc.
Http.send! and Http.get! take a Url rather than a Str, so a URL is
checked once, before any host effect runs, instead of at the socket.
A URL written out in the source needs no call at all: Roc reaches for
from_quote wherever a quoted literal is expected to have type Url, so
the literal is validated at compile time and a bad one is a compile error.
body = Http.get_utf8!("http://127.0.0.1:8000/data.json")?
A URL built at runtime goes through parse, which answers a ParseErr.
resolve follows a relative reference against a base URL, which is what a
link found in a fetched document needs, and to_str turns any of them back
into text.
Parsing is deliberately stricter than a browser's. Hosts must be ASCII DNS
names, dotted-decimal IPv4 addresses, or bracketed IPv6 addresses made from
hexadecimal groups with optional :: elision. IPv4-in-IPv6 and Unicode
domain names are unsupported, and inputs a browser would repair -- missing
authority slashes, backslashes -- are rejected rather than fixed.
Vendored verbatim from roc-lang/basic-cli's platform/Url.roc, which is
published under the same Universal Permissive License 1.0 this repository
uses. The shared roc-lang/http package supplies Request, Response,
Method and Header but deliberately not a URL parser. Keeping this a
byte-for-byte copy means the parser's behaviour, its error set, and its 67
inline tests can be re-synced from upstream by replacing the file.
Parse a dynamic string as an absolute HTTP or HTTPS URL.
The input must contain an explicit scheme and authority. Its host is
lowercased, default ports are removed, dot path segments are normalized,
and non-ASCII path, query, and fragment bytes are percent-encoded.
Convert a quoted literal to a URL using the same validation as parse.
Roc calls this automatically when a quoted literal is expected to have
type Url. A rejected literal reports a descriptive BadQuotedBytes error.
parser_for : encoding -> state -> Try({ value : Url, rest : state }, err)
where [
encoding.parse_str : encoding, state -> Try({ value : Str, rest : state }, err),
encoding.invalid_value : encoding, state -> err,
]
Parse a URL from a string value supplied by a generic encoding.
encoder_for : encoding -> Url, state -> Try(state, err)
where [
encoding.encode_str : Str, state -> Try(state, err),
]
Encode a URL as its canonical string through a generic encoding.
A reason a URL or relative reference could not be parsed.
This error set describes this module's strict HTTP/HTTPS subset. Inputs
that browsers might repair, such as missing authority slashes or
backslashes, are rejected instead.