Utility library
#include "crow/uri.hpp"
namespace Crow;
class Uri;
This class holds a URI, assumed to follow the format:
scheme: [//] [ [user [:password] @] host [:port] ] [/path] [?query] [#fragment]
static constexpr int Uri::lone_keys = 1;
Flag used in the make_query()
function.
Uri::Uri() noexcept;
The default constructor produces an empty URI.
explicit Uri::Uri(std::string_view s);
This constructor parses a URI supplied as a string. This will throw
std::invalid_argument
if the URI is invalid.
Uri::Uri(std::string_view scheme,
std::string_view user, std::string_view password,
std::string_view host, uint16_t port = 0,
std::string_view path = {}, std::string_view query = {},
std::string_view fragment = {});
This constructor assembles a URI from its component parts (following the same
rules as the individual set_*()
functions described below). This will throw
std::invalid_argument
if the arguments do not form a valid URI.
Uri::Uri(const Uri& u);
Uri::Uri(Uri&& u) noexcept;
Uri::~Uri() noexcept;
Uri& Uri::operator=(const Uri& u);
Uri& Uri::operator=(Uri&& u) noexcept;
Other life cycle functions.
bool Uri::has_slashes() const noexcept;
bool Uri::has_user() const noexcept;
bool Uri::has_password() const noexcept;
bool Uri::has_host() const noexcept;
bool Uri::has_port() const noexcept;
bool Uri::has_path() const noexcept;
bool Uri::has_query() const noexcept;
bool Uri::has_fragment() const noexcept;
Query whether a given URI element is present. There is no has_scheme()
because the scheme is always present if the URI is not empty.
std::string Uri::scheme() const;
std::string Uri::user() const;
std::string Uri::password() const;
std::string Uri::host() const;
uint16_t Uri::port() const noexcept;
std::string Uri::path() const;
std::string Uri::query() const;
std::string Uri::fragment() const;
Query the value of a given URI element. The returned strings do not include
the associated punctuation (e.g. scheme()
will not have a trailing colon or
slashes). In some cases this means that the corresponding has_*()
function
must also be checked in order to distinguish between an element that is
absent and one that is present but with an empty value (e.g. a URI ending in
a question mark is considered to include an empty query string, which is not
the same thing as one with no query part).
void Uri::set_scheme(std::string_view new_scheme, bool smart = true);
void Uri::set_user(std::string_view new_user);
void Uri::set_password(std::string_view new_password);
void Uri::set_host(std::string_view new_host);
void Uri::set_port(uint16_t new_port);
void Uri::set_path(std::string_view new_path);
void Uri::set_query(std::string_view new_query);
void Uri::set_fragment(std::string_view new_fragment);
Change the value of a given URI element. The string supplied will be escaped
when necessary. Passing an empty string is equivalent to clearing the element
only for elements that do not distinguish between an empty value and a missing
element; this is not true of the query and fragment elements (e.g.
set_user("")
is equivalent to clear_user()
, but set_query("")
is not
equivalent to clear_query()
).
The scheme will always be converted to lower case. If the smart
argument to
set_scheme()
is true (this is the default), and the scheme supplied does
not end in "://"
, the colon will be added, and the slashes unless the
scheme is "mailto"
.
All of these except set_scheme()
will throw std::invalid_argument
if the
existing URI is empty, or under the following circumstances:
set_scheme()
if the scheme is invalid (it must match [a-z][a-z0-9.+-]*(:(//)?)?
).set_user()
if the host is empty and the new user is not empty.set_password()
if the user or host is empty and the new password is not empty.set_path()
if the path contains "//"
.void Uri::clear_user() noexcept;
void Uri::clear_password() noexcept;
void Uri::clear_host() noexcept;
void Uri::clear_port() noexcept;
void Uri::clear_path() noexcept;
void Uri::clear_query() noexcept;
void Uri::clear_fragment() noexcept;
Remove a given URI element. There is no function to clear the scheme because the scheme is always required.
void Uri::append_path(std::string_view new_path);
Uri& Uri::operator/=(std::string_view s);
Uri operator/(const Uri& u, std::string_view s);
Append one or more file path elements to the URI’s path. Appending an absolute
path (one that starts with a slash) will discard the original path and behave
like set_path()
. These will throw std::invalid_argument
if the path is
invalid (contains two consecutive slashes).
void Uri::clear() noexcept;
Resets the URI to an empty string.
Uri Uri::doc() const;
Uri Uri::base() const;
Uri Uri::parent() const;
Uri Uri::root() const;
These return related URLs:
doc()
function discards the fragment part (as for clear_fragment()
).base()
discards the query and fragment parts.parent()
discards the last element of the path, if any.root()
discards the entire path and returns the root of the host directory tree (as for set_path("/")
).bool Uri::empty() const noexcept;
True if the URI is empty.
size_t Uri::hash() const noexcept;
struct std::hash<Uri>;
Hash functions.
bool Uri::is_root() const noexcept;
True if the URI refers to the root of the host directory tree (the path part
is empty or "/"
).
std::string Uri::path_dir() const;
std::string Uri::path_leaf() const;
Split the path element into a directory path and a leaf name. If path_dir()
is not empty, it will always start and end with a slash (it may just be a lone
slash). If the whole path ends with a slash, it is assumed to be a directory
name, and path_leaf()
will be empty.
std::string Uri::str() const;
std::ostream& operator<<(std::ostream& out, const Uri& u);
Return the URI as a string.
bool Uri::try_parse(std::string_view s);
Attempts to parse the given string as a URI. On success, this changes the current object to hold the new URI and returns true; on failure, it returns false and leaves the object unchanged.
static std::string Uri::encode(std::string_view s, std::string_view exempt = {});
static std::string Uri::decode(std::string_view s);
These apply percent encoding to a string. Safe bytes, left unencoded, are the
ASCII alphanumerics plus [-._~]
; all other bytes are encoded unless they
appear in the exempt string.
template <std::ranges::range R>
static std::string Uri::make_query(const R& range, char delimiter = '&',
int flags = 0);
static std::vector<std::pair<std::string, std::string>>
Uri::parse_query(std::string_view query, char delimiter = 0);
Construct or deconstruct a query string. The range argument to make_query()
is expected to contain pairs whose first and second fields are string views or
convertible to them; the delimiter character is inserted between key/value
pairs; an equals sign is inserted between keys and values, except that it will
be left out if the value is empty and the lone_keys
flag is set.
The parse_query()
function breaks down a query string into a vector of
key/value pairs; if no delimiter is explicitly supplied, whichever of '&'
or ';'
appears first in the string will be used. Key and value strings are
percent encoded by make_query()
and decoded by parse_query()
.
std::strong_ordering operator<=>(const Uri& u, const Uri& v) noexcept;
bool operator==(const Uri& u, const Uri& v) noexcept;
bool operator!=(const Uri& u, const Uri& v) noexcept;
bool operator<(const Uri& u, const Uri& v) noexcept;
bool operator>(const Uri& u, const Uri& v) noexcept;
bool operator<=(const Uri& u, const Uri& v) noexcept;
bool operator>=(const Uri& u, const Uri& v) noexcept;
Comparison operators. These perform a simple string comparison on the URI string.
namespace Literals {
inline Uri operator""_uri(const char* p, size_t n);
}
URI literal operator. This calls the string-based constructor, and will throw the same exceptions.