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: ...@@ -233,6 +233,17 @@ public:
/// ///
const str_bounds& authority() const; 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. /// @brief Exchanges the contents of <code>this</code> and @p other.
/// @param other {@link caf::io::uri uri} object that should exchange its /// @param other {@link caf::io::uri uri} object that should exchange its
......
...@@ -68,36 +68,41 @@ class uri_private : public ref_counted { ...@@ -68,36 +68,41 @@ class uri_private : public ref_counted {
// authority subcomponents // authority subcomponents
str_bounds m_host_; str_bounds m_host_;
str_bounds m_port_; str_bounds m_port_;
str_bounds m_user_information_;
// convenience fields // convenience fields
uint16_t m_int_port_; uint16_t m_int_port_;
void clear() { void clear() {
m_uri_.clear(); m_uri_.clear();
m_path_ = make_tuple(m_uri_.end(),m_uri_.end()); m_path_ = make_tuple(end(m_uri_), end(m_uri_));
m_query_ = make_tuple(m_uri_.end(),m_uri_.end()); m_query_ = make_tuple(end(m_uri_), end(m_uri_));
m_scheme_ = make_tuple(m_uri_.end(),m_uri_.end()); m_scheme_ = make_tuple(end(m_uri_), end(m_uri_));
m_fragment_ = make_tuple(m_uri_.end(),m_uri_.end()); m_fragment_ = make_tuple(end(m_uri_), end(m_uri_));
m_authority_ = make_tuple(m_uri_.end(),m_uri_.end()); 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 // this parses the given uri to the form
// {scheme} {authority} {path} {query} {fragment} // {scheme} {authority} {path} {query} {fragment}
bool parse_uri(const string& what) { bool parse_uri(const string& what) {
m_flag_ = default_flag;
auto empty = [](const str_bounds& bounds) { auto empty = [](const str_bounds& bounds) {
return bounds.first >= bounds.second; return bounds.first >= bounds.second;
}; };
m_flag_ = default_flag;
m_uri_.clear(); m_uri_.clear();
m_uri_ = what; m_uri_ = what;
m_host_ = make_pair(begin(m_uri_), begin(m_uri_)); 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_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_query_ = make_pair(begin(m_uri_), begin(m_uri_));
m_scheme_ = 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_fragment_ = make_pair(begin(m_uri_), begin(m_uri_));
m_authority_ = 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 from_itr = begin(m_uri_);
auto to_itr = find(begin(m_uri_), end(m_uri_), ':'); auto to_itr = find(begin(m_uri_), end(m_uri_), ':');
if (to_itr == m_uri_.end()) { if (to_itr == m_uri_.end()) {
...@@ -118,17 +123,29 @@ class uri_private : public ref_counted { ...@@ -118,17 +123,29 @@ class uri_private : public ref_counted {
if (empty(m_authority_)) { if (empty(m_authority_)) {
return false; return false;
} }
// parse user info from authority
auto at = find(m_authority_.first, m_authority_.second, '@'); auto at = find(m_authority_.first, m_authority_.second, '@');
if (at != 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 // parse host and port
auto col = find(m_authority_.first, m_authority_.second, ':'); // 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) { 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); m_port_ = make_pair(col + 1, m_authority_.second);
} else { } else {
m_host_ = m_authority_; m_host_ = make_pair(at, m_authority_.second);
m_port_ = make_pair(m_authority_.second, m_authority_.second); m_port_ = make_pair(m_authority_.second, m_authority_.second);
} }
if (!empty(m_host_) && *m_host_.first == '[') { if (!empty(m_host_) && *m_host_.first == '[') {
...@@ -189,6 +206,10 @@ public: ...@@ -189,6 +206,10 @@ public:
inline const str_bounds& port() const { return m_port_; } inline const str_bounds& port() const { return m_port_; }
inline uint16_t port_as_int() const { return m_int_port_; } 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 { inline bool host_is_ipv4addr() const {
return m_flag_ == ipv4_flag; return m_flag_ == ipv4_flag;
...@@ -288,6 +309,10 @@ const str_bounds& uri::authority() const { ...@@ -288,6 +309,10 @@ const str_bounds& uri::authority() const {
return d_->authority(); return d_->authority();
} }
const str_bounds& uri::user_information() const {
return d_->user_information();
}
bool uri::host_is_ipv4addr() const { bool uri::host_is_ipv4addr() const {
return d_->host_is_ipv4addr(); return d_->host_is_ipv4addr();
} }
......
...@@ -40,14 +40,15 @@ namespace { ...@@ -40,14 +40,15 @@ namespace {
using str_bounds = std::pair<std::string::iterator, std::string::iterator>; using str_bounds = std::pair<std::string::iterator, std::string::iterator>;
// building blocks // building blocks
#define MY_SCHEME "my_scheme" #define MY_SCHEME "my_scheme"
#define MY_HOST "my_host" #define MY_HOST "my_host"
#define MY_V4_HOST "1.2.3.4" #define MY_V4_HOST "1.2.3.4"
#define MY_V6_HOST "2001:db8::ff00:42:8329" #define MY_V6_HOST "2001:db8::ff00:42:8329"
#define MY_PORT "8080" #define MY_PORT "8080"
#define MY_PATH "my_path" #define MY_PATH "my_path"
#define MY_QUERY "my_query" #define MY_QUERY "my_query"
#define MY_FRAGMENT "my_fragment" #define MY_FRAGMENT "my_fragment"
#define MY_USER_INFO "my_user:my_passwd"
// valid URIs // valid URIs
constexpr char uri_00[] = MY_SCHEME ":"; constexpr char uri_00[] = MY_SCHEME ":";
...@@ -62,9 +63,8 @@ constexpr char uri_07[] = MY_SCHEME "://" MY_HOST ":" MY_PORT "/" MY_PATH "?" ...@@ -62,9 +63,8 @@ constexpr char uri_07[] = MY_SCHEME "://" MY_HOST ":" MY_PORT "/" MY_PATH "?"
MY_QUERY "#" MY_FRAGMENT; MY_QUERY "#" MY_FRAGMENT;
constexpr char uri_08[] = MY_SCHEME "://" MY_HOST ":" MY_PORT "?" MY_QUERY; 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_09[] = MY_SCHEME "://" MY_HOST ":" MY_PORT "#" MY_FRAGMENT;
constexpr char uri_10[] = MY_SCHEME "://" ":" MY_PORT; constexpr char uri_10[] = MY_SCHEME "://:" MY_PORT;
constexpr char uri_11[] = MY_SCHEME "://" MY_USER_INFO "@" MY_HOST;
// invalid URIs
class config : public actor_system_config { class config : public actor_system_config {
public: public:
...@@ -103,6 +103,7 @@ CAF_TEST(valid_uris) { ...@@ -103,6 +103,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_00.path())); CAF_CHECK(empty(u_00.path()));
CAF_CHECK(empty(u_00.query())); CAF_CHECK(empty(u_00.query()));
CAF_CHECK(empty(u_00.fragment())); CAF_CHECK(empty(u_00.fragment()));
CAF_CHECK(empty(u_00.user_information()));
CAF_CHECK_EQUAL(string_of(u_00.scheme()), MY_SCHEME); CAF_CHECK_EQUAL(string_of(u_00.scheme()), MY_SCHEME);
auto u_01 = uri::make(uri_01).value(); auto u_01 = uri::make(uri_01).value();
CAF_CHECK_EQUAL(uri_01, u_01.str()); CAF_CHECK_EQUAL(uri_01, u_01.str());
...@@ -112,6 +113,7 @@ CAF_TEST(valid_uris) { ...@@ -112,6 +113,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_01.path())); CAF_CHECK(!empty(u_01.path()));
CAF_CHECK(empty(u_01.query())); CAF_CHECK(empty(u_01.query()));
CAF_CHECK(empty(u_01.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_01.path()), MY_PATH); CAF_CHECK_EQUAL(string_of(u_01.path()), MY_PATH);
auto u_02 = uri::make(uri_02).value(); auto u_02 = uri::make(uri_02).value();
...@@ -122,6 +124,7 @@ CAF_TEST(valid_uris) { ...@@ -122,6 +124,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_02.path())); CAF_CHECK(!empty(u_02.path()));
CAF_CHECK(empty(u_02.query())); CAF_CHECK(empty(u_02.query()));
CAF_CHECK(empty(u_02.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_02.path()), MY_PATH); CAF_CHECK_EQUAL(string_of(u_02.path()), MY_PATH);
auto u_03 = uri::make(uri_03).value(); auto u_03 = uri::make(uri_03).value();
...@@ -132,6 +135,7 @@ CAF_TEST(valid_uris) { ...@@ -132,6 +135,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_03.path())); CAF_CHECK(empty(u_03.path()));
CAF_CHECK(empty(u_03.query())); CAF_CHECK(empty(u_03.query()));
CAF_CHECK(empty(u_03.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_03.host()), MY_HOST); CAF_CHECK_EQUAL(string_of(u_03.host()), MY_HOST);
auto u_04 = uri::make(uri_04).value(); auto u_04 = uri::make(uri_04).value();
...@@ -141,6 +145,7 @@ CAF_TEST(valid_uris) { ...@@ -141,6 +145,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_04.path())); CAF_CHECK(empty(u_04.path()));
CAF_CHECK(empty(u_04.query())); CAF_CHECK(empty(u_04.query()));
CAF_CHECK(empty(u_04.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_04.host()), MY_HOST); CAF_CHECK_EQUAL(string_of(u_04.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_04.port()), MY_PORT); CAF_CHECK_EQUAL(string_of(u_04.port()), MY_PORT);
...@@ -152,6 +157,7 @@ CAF_TEST(valid_uris) { ...@@ -152,6 +157,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_05.path())); CAF_CHECK(!empty(u_05.path()));
CAF_CHECK(empty(u_05.query())); CAF_CHECK(empty(u_05.query()));
CAF_CHECK(empty(u_05.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_05.host()), MY_HOST); CAF_CHECK_EQUAL(string_of(u_05.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_05.port()), MY_PORT); CAF_CHECK_EQUAL(string_of(u_05.port()), MY_PORT);
...@@ -164,6 +170,7 @@ CAF_TEST(valid_uris) { ...@@ -164,6 +170,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_06.path())); CAF_CHECK(!empty(u_06.path()));
CAF_CHECK(!empty(u_06.query())); CAF_CHECK(!empty(u_06.query()));
CAF_CHECK(empty(u_06.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_06.host()), MY_HOST); CAF_CHECK_EQUAL(string_of(u_06.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_06.port()), MY_PORT); CAF_CHECK_EQUAL(string_of(u_06.port()), MY_PORT);
...@@ -177,6 +184,7 @@ CAF_TEST(valid_uris) { ...@@ -177,6 +184,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(!empty(u_07.path())); CAF_CHECK(!empty(u_07.path()));
CAF_CHECK(!empty(u_07.query())); CAF_CHECK(!empty(u_07.query()));
CAF_CHECK(!empty(u_07.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_07.host()), MY_HOST); CAF_CHECK_EQUAL(string_of(u_07.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_07.port()), MY_PORT); CAF_CHECK_EQUAL(string_of(u_07.port()), MY_PORT);
...@@ -191,6 +199,7 @@ CAF_TEST(valid_uris) { ...@@ -191,6 +199,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_08.path())); CAF_CHECK(empty(u_08.path()));
CAF_CHECK(!empty(u_08.query())); CAF_CHECK(!empty(u_08.query()));
CAF_CHECK(empty(u_08.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_08.host()), MY_HOST); CAF_CHECK_EQUAL(string_of(u_08.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_08.port()), MY_PORT); CAF_CHECK_EQUAL(string_of(u_08.port()), MY_PORT);
...@@ -203,6 +212,7 @@ CAF_TEST(valid_uris) { ...@@ -203,6 +212,7 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_09.path())); CAF_CHECK(empty(u_09.path()));
CAF_CHECK(empty(u_09.query())); CAF_CHECK(empty(u_09.query()));
CAF_CHECK(!empty(u_09.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_09.host()), MY_HOST); CAF_CHECK_EQUAL(string_of(u_09.host()), MY_HOST);
CAF_CHECK_EQUAL(string_of(u_09.port()), MY_PORT); CAF_CHECK_EQUAL(string_of(u_09.port()), MY_PORT);
...@@ -215,8 +225,21 @@ CAF_TEST(valid_uris) { ...@@ -215,8 +225,21 @@ CAF_TEST(valid_uris) {
CAF_CHECK(empty(u_10.path())); CAF_CHECK(empty(u_10.path()));
CAF_CHECK(empty(u_10.query())); CAF_CHECK(empty(u_10.query()));
CAF_CHECK(empty(u_10.fragment())); 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.scheme()), MY_SCHEME);
CAF_CHECK_EQUAL(string_of(u_10.port()), MY_PORT); 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) { CAF_TEST(ipv4_vs_ipv6) {
...@@ -227,7 +250,3 @@ CAF_TEST(ipv4_vs_ipv6) { ...@@ -227,7 +250,3 @@ CAF_TEST(ipv4_vs_ipv6) {
CAF_CHECK(u_ipv6.host_is_ipv6addr()); CAF_CHECK(u_ipv6.host_is_ipv6addr());
CAF_CHECK_EQUAL(string_of(u_ipv6.host()), MY_V6_HOST); 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