Commit ffb044f1 authored by Joseph Noir's avatar Joseph Noir

Update URI to handle ipv6 and user information

parent 66e71713
......@@ -233,6 +233,17 @@ public:
///
const str_bounds& authority() const;
///
/// @brief Get the user information subcomponent of authority.
///
/// The userinfo subcomponent may consist of a user name and, optionally,
/// scheme-specific information about how to gain authorization to access
/// the resource.
/// @returns The user information subcomponent of {@link authority()}.
///
const str_bounds& user_information() const;
///
/// @brief Exchanges the contents of <code>this</code> and @p other.
/// @param other {@link caf::io::uri uri} object that should exchange its
......
......@@ -68,36 +68,41 @@ class uri_private : public ref_counted {
// authority subcomponents
str_bounds m_host_;
str_bounds m_port_;
str_bounds m_user_information_;
// convenience fields
uint16_t m_int_port_;
void clear() {
m_uri_.clear();
m_path_ = make_tuple(m_uri_.end(),m_uri_.end());
m_query_ = make_tuple(m_uri_.end(),m_uri_.end());
m_scheme_ = make_tuple(m_uri_.end(),m_uri_.end());
m_fragment_ = make_tuple(m_uri_.end(),m_uri_.end());
m_authority_ = make_tuple(m_uri_.end(),m_uri_.end());
m_path_ = make_tuple(end(m_uri_), end(m_uri_));
m_query_ = make_tuple(end(m_uri_), end(m_uri_));
m_scheme_ = make_tuple(end(m_uri_), end(m_uri_));
m_fragment_ = make_tuple(end(m_uri_), end(m_uri_));
m_authority_ = make_tuple(end(m_uri_), end(m_uri_));
m_host_ = make_tuple(end(m_uri_), end(m_uri_));
m_port_ = make_tuple(end(m_uri_), end(m_uri_));
m_user_information_ = make_pair(end(m_uri_), end(m_uri_));
}
// this parses the given uri to the form
// {scheme} {authority} {path} {query} {fragment}
bool parse_uri(const string& what) {
m_flag_ = default_flag;
auto empty = [](const str_bounds& bounds) {
return bounds.first >= bounds.second;
};
m_flag_ = default_flag;
m_uri_.clear();
m_uri_ = what;
m_host_ = make_pair(begin(m_uri_), begin(m_uri_));
m_port_ = make_pair(begin(m_uri_), begin(m_uri_));
m_path_ = make_pair(begin(m_uri_), begin(m_uri_));
m_port_ = make_pair(begin(m_uri_), begin(m_uri_));
m_query_ = make_pair(begin(m_uri_), begin(m_uri_));
m_scheme_ = make_pair(begin(m_uri_), begin(m_uri_));
m_fragment_ = make_pair(begin(m_uri_), begin(m_uri_));
m_authority_ = make_pair(begin(m_uri_), begin(m_uri_));
// find ':' for scheme boundries
m_user_information_ = make_pair(begin(m_uri_), begin(m_uri_));
// find ':' for scheme boundaries
auto from_itr = begin(m_uri_);
auto to_itr = find(begin(m_uri_), end(m_uri_), ':');
if (to_itr == m_uri_.end()) {
......@@ -118,17 +123,29 @@ class uri_private : public ref_counted {
if (empty(m_authority_)) {
return false;
}
// parse user info from authority
auto at = find(m_authority_.first, m_authority_.second, '@');
if (at != m_authority_.second) {
m_user_information_ = make_pair(m_authority_.first, at);
// skip the '@' character
at += 1;
} else {
// reset if we found nothing
at = m_authority_.first;
}
// For our purpose we assume not to have a user info
auto col = find(m_authority_.first, m_authority_.second, ':');
// parse host and port
// look for closing ']' in case host is an ipv6 address
auto col = find(at, m_authority_.second, ']');
if (col == m_authority_.second) {
// if no bracket is found, reset itr
col = at;
}
col = find(col, m_authority_.second, ':');
if (col != m_authority_.second) {
m_host_ = make_pair(m_authority_.first, col);
m_host_ = make_pair(at, col);
m_port_ = make_pair(col + 1, m_authority_.second);
} else {
m_host_ = m_authority_;
m_host_ = make_pair(at, m_authority_.second);
m_port_ = make_pair(m_authority_.second, m_authority_.second);
}
if (!empty(m_host_) && *m_host_.first == '[') {
......@@ -190,6 +207,10 @@ public:
inline uint16_t port_as_int() const { return m_int_port_; }
inline const str_bounds& user_information() const {
return m_user_information_;
}
inline bool host_is_ipv4addr() const {
return m_flag_ == ipv4_flag;
}
......@@ -288,6 +309,10 @@ const str_bounds& uri::authority() const {
return d_->authority();
}
const str_bounds& uri::user_information() const {
return d_->user_information();
}
bool uri::host_is_ipv4addr() const {
return d_->host_is_ipv4addr();
}
......
......@@ -48,6 +48,7 @@ using str_bounds = std::pair<std::string::iterator, std::string::iterator>;
#define MY_PATH "my_path"
#define MY_QUERY "my_query"
#define MY_FRAGMENT "my_fragment"
#define MY_USER_INFO "my_user:my_passwd"
// valid URIs
constexpr char uri_00[] = MY_SCHEME ":";
......@@ -62,9 +63,8 @@ constexpr char uri_07[] = MY_SCHEME "://" MY_HOST ":" MY_PORT "/" MY_PATH "?"
MY_QUERY "#" MY_FRAGMENT;
constexpr char uri_08[] = MY_SCHEME "://" MY_HOST ":" MY_PORT "?" MY_QUERY;
constexpr char uri_09[] = MY_SCHEME "://" MY_HOST ":" MY_PORT "#" MY_FRAGMENT;
constexpr char uri_10[] = MY_SCHEME "://" ":" MY_PORT;
// invalid URIs
constexpr char uri_10[] = MY_SCHEME "://:" MY_PORT;
constexpr char uri_11[] = MY_SCHEME "://" MY_USER_INFO "@" MY_HOST;
class config : public actor_system_config {
public:
......@@ -103,6 +103,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_00.path()));
CAF_CHECK(empty(u_00.query()));
CAF_CHECK(empty(u_00.fragment()));
CAF_CHECK(empty(u_00.user_information()));
CAF_CHECK_EQUAL(string_of(u_00.scheme()), MY_SCHEME);
auto u_01 = uri::make(uri_01).value();
CAF_CHECK_EQUAL(uri_01, u_01.str());
......@@ -112,6 +113,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_01.path()));
CAF_CHECK(empty(u_01.query()));
CAF_CHECK(empty(u_01.fragment()));
CAF_CHECK(empty(u_01.user_information()));
CAF_CHECK_EQUAL(string_of(u_01.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_01.path()), MY_PATH);
auto u_02 = uri::make(uri_02).value();
......@@ -122,6 +124,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_02.path()));
CAF_CHECK(empty(u_02.query()));
CAF_CHECK(empty(u_02.fragment()));
CAF_CHECK(empty(u_02.user_information()));
CAF_CHECK_EQUAL(string_of(u_02.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_02.path()), MY_PATH);
auto u_03 = uri::make(uri_03).value();
......@@ -132,6 +135,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_03.path()));
CAF_CHECK(empty(u_03.query()));
CAF_CHECK(empty(u_03.fragment()));
CAF_CHECK(empty(u_03.user_information()));
CAF_CHECK_EQUAL(string_of(u_03.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_03.host()), MY_HOST);
auto u_04 = uri::make(uri_04).value();
......@@ -141,6 +145,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_04.path()));
CAF_CHECK(empty(u_04.query()));
CAF_CHECK(empty(u_04.fragment()));
CAF_CHECK(empty(u_04.user_information()));
CAF_CHECK_EQUAL(string_of(u_04.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_04.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_04.port()), MY_PORT);
......@@ -152,6 +157,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_05.path()));
CAF_CHECK(empty(u_05.query()));
CAF_CHECK(empty(u_05.fragment()));
CAF_CHECK(empty(u_05.user_information()));
CAF_CHECK_EQUAL(string_of(u_05.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_05.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_05.port()), MY_PORT);
......@@ -164,6 +170,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_06.path()));
CAF_CHECK(!empty(u_06.query()));
CAF_CHECK(empty(u_06.fragment()));
CAF_CHECK(empty(u_06.user_information()));
CAF_CHECK_EQUAL(string_of(u_06.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_06.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_06.port()), MY_PORT);
......@@ -177,6 +184,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_07.path()));
CAF_CHECK(!empty(u_07.query()));
CAF_CHECK(!empty(u_07.fragment()));
CAF_CHECK(empty(u_07.user_information()));
CAF_CHECK_EQUAL(string_of(u_07.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_07.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_07.port()), MY_PORT);
......@@ -191,6 +199,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_08.path()));
CAF_CHECK(!empty(u_08.query()));
CAF_CHECK(empty(u_08.fragment()));
CAF_CHECK(empty(u_08.user_information()));
CAF_CHECK_EQUAL(string_of(u_08.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_08.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_08.port()), MY_PORT);
......@@ -203,6 +212,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_09.path()));
CAF_CHECK(empty(u_09.query()));
CAF_CHECK(!empty(u_09.fragment()));
CAF_CHECK(empty(u_09.user_information()));
CAF_CHECK_EQUAL(string_of(u_09.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_09.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_09.port()), MY_PORT);
......@@ -215,8 +225,21 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_10.path()));
CAF_CHECK(empty(u_10.query()));
CAF_CHECK(empty(u_10.fragment()));
CAF_CHECK(empty(u_10.user_information()));
CAF_CHECK_EQUAL(string_of(u_10.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_10.port()), MY_PORT);
auto u_11 = uri::make(uri_11).value();
CAF_CHECK_EQUAL(uri_11, u_11.str());
CAF_CHECK(!empty(u_11.scheme()));
CAF_CHECK(!empty(u_11.host()));
CAF_CHECK(empty(u_11.port()));
CAF_CHECK(empty(u_11.path()));
CAF_CHECK(empty(u_11.query()));
CAF_CHECK(empty(u_11.fragment()));
CAF_CHECK(!empty(u_11.user_information()));
CAF_CHECK_EQUAL(string_of(u_11.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_11.user_information()), MY_USER_INFO);
CAF_CHECK_EQUAL(string_of(u_11.host()), MY_HOST);
}
CAF_TEST(ipv4_vs_ipv6) {
......@@ -227,7 +250,3 @@ CAF_TEST(ipv4_vs_ipv6) {
CAF_CHECK(u_ipv6.host_is_ipv6addr());
CAF_CHECK_EQUAL(string_of(u_ipv6.host()), MY_V6_HOST);
}
CAF_TEST(invalid_uri) {
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment