Repository: kudu Updated Branches: refs/heads/master 4ec2598a3 -> 137775bdd
[util] Add ParseStringsWithScheme in net_util This commit adds a new util to allow parsing address with scheme, e.g. '<fs>://<host>:<port>/<path>' into a <host>:<port> pair. Change-Id: I2447ab80e0b0737c4eb2ba8216769a52b5c07ce0 Reviewed-on: http://gerrit.cloudera.org:8080/11843 Reviewed-by: Adar Dembo <a...@cloudera.com> Tested-by: Kudu Jenkins Reviewed-by: Alexey Serbin <aser...@cloudera.com> Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/32a4fe16 Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/32a4fe16 Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/32a4fe16 Branch: refs/heads/master Commit: 32a4fe168aab97a0905283506da498304774748f Parents: 4ec2598 Author: Hao Hao <hao....@cloudera.com> Authored: Wed Oct 31 17:46:20 2018 -0700 Committer: Hao Hao <hao....@cloudera.com> Committed: Thu Nov 1 20:03:56 2018 +0000 ---------------------------------------------------------------------- src/kudu/util/net/net_util-test.cc | 46 +++++++++++++++++++++++++++++--- src/kudu/util/net/net_util.cc | 47 +++++++++++++++++++++++++++++++-- src/kudu/util/net/net_util.h | 17 +++++++++++- 3 files changed, 104 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/32a4fe16/src/kudu/util/net/net_util-test.cc ---------------------------------------------------------------------- diff --git a/src/kudu/util/net/net_util-test.cc b/src/kudu/util/net/net_util-test.cc index 202ec6b..8ad0fba 100644 --- a/src/kudu/util/net/net_util-test.cc +++ b/src/kudu/util/net/net_util-test.cc @@ -76,13 +76,53 @@ TEST_F(NetUtilTest, TestParseAddresses) { // Test some invalid addresses. Status s = DoParseBindAddresses("0.0.0.0:xyz", &ret); - ASSERT_STR_CONTAINS(s.ToString(), "Invalid port"); + ASSERT_STR_CONTAINS(s.ToString(), "invalid port"); s = DoParseBindAddresses("0.0.0.0:100000", &ret); - ASSERT_STR_CONTAINS(s.ToString(), "Invalid port"); + ASSERT_STR_CONTAINS(s.ToString(), "invalid port"); s = DoParseBindAddresses("0.0.0.0:", &ret); - ASSERT_STR_CONTAINS(s.ToString(), "Invalid port"); + ASSERT_STR_CONTAINS(s.ToString(), "invalid port"); +} + +TEST_F(NetUtilTest, TestParseAddressesWithScheme) { + vector<HostPort> hostports; + const uint16_t kDefaultPort = 12345; + + EXPECT_OK(HostPort::ParseStringsWithScheme("", kDefaultPort, &hostports)); + EXPECT_TRUE(hostports.empty()); + + EXPECT_OK(HostPort::ParseStringsWithScheme(",,,", kDefaultPort, &hostports)); + EXPECT_TRUE(hostports.empty()); + + EXPECT_OK(HostPort::ParseStringsWithScheme("http://foo-bar-baz:1234", kDefaultPort, &hostports)); + EXPECT_EQ(vector<HostPort>({ HostPort("foo-bar-baz", 1234) }), hostports); + + EXPECT_OK(HostPort::ParseStringsWithScheme("http://foo-bar-baz:1234/path", + kDefaultPort, &hostports)); + EXPECT_EQ(vector<HostPort>({ HostPort("foo-bar-baz", 1234) }), hostports); + + EXPECT_OK(HostPort::ParseStringsWithScheme("http://abc:1234,xyz", kDefaultPort, &hostports)); + EXPECT_EQ(vector<HostPort>({ HostPort("abc", 1234), HostPort("xyz", kDefaultPort) }), + hostports); + + // Test some invalid addresses. + Status s = HostPort::ParseStringsWithScheme("abc:1234/path", kDefaultPort, &hostports); + EXPECT_TRUE(s.IsInvalidArgument()); + ASSERT_STR_CONTAINS(s.ToString(), "invalid port"); + + s = HostPort::ParseStringsWithScheme("://scheme:12", kDefaultPort, &hostports); + EXPECT_TRUE(s.IsInvalidArgument()); + ASSERT_STR_CONTAINS(s.ToString(), "invalid scheme format"); + + s = HostPort::ParseStringsWithScheme("http:///path", kDefaultPort, &hostports); + EXPECT_TRUE(s.IsInvalidArgument()); + ASSERT_STR_CONTAINS(s.ToString(), "invalid address format"); + + s = HostPort::ParseStringsWithScheme("http://abc:1234,://scheme,xyz", + kDefaultPort, &hostports); + EXPECT_TRUE(s.IsInvalidArgument()); + ASSERT_STR_CONTAINS(s.ToString(), "invalid scheme format"); } TEST_F(NetUtilTest, TestResolveAddresses) { http://git-wip-us.apache.org/repos/asf/kudu/blob/32a4fe16/src/kudu/util/net/net_util.cc ---------------------------------------------------------------------- diff --git a/src/kudu/util/net/net_util.cc b/src/kudu/util/net/net_util.cc index 520882f..482747e 100644 --- a/src/kudu/util/net/net_util.cc +++ b/src/kudu/util/net/net_util.cc @@ -138,7 +138,7 @@ Status HostPort::ParseString(const string& str, uint16_t default_port) { port = default_port; } else if (!SimpleAtoi(p.second, &port) || port > 65535) { - return Status::InvalidArgument("Invalid port", str); + return Status::InvalidArgument("invalid port", str); } host_.swap(p.first); @@ -146,6 +146,31 @@ Status HostPort::ParseString(const string& str, uint16_t default_port) { return Status::OK(); } +Status HostPort::ParseStringWithScheme(const string& str, uint16_t default_port) { + string str_copy(str); + const string kSchemeSeparator = "://"; + const string kPathSeparator = "/"; + + auto scheme_idx = str_copy.find(kSchemeSeparator); + + if (scheme_idx == 0) { + return Status::InvalidArgument("invalid scheme format", str_copy); + } + + if (scheme_idx != string::npos) { + str_copy.erase(0, scheme_idx + kSchemeSeparator.size()); + auto path_idx = str_copy.find(kPathSeparator); + if (path_idx == 0) { + return Status::InvalidArgument("invalid address format", str_copy); + } + if (path_idx != string::npos) { + str_copy.erase(path_idx, str_copy.size()); + } + } + + return ParseString(str_copy, default_port); +} + Status HostPort::ResolveAddresses(vector<Sockaddr>* addresses) const { TRACE_EVENT1("net", "HostPort::ResolveAddresses", "host", host_); @@ -179,11 +204,29 @@ Status HostPort::ResolveAddresses(vector<Sockaddr>* addresses) const { Status HostPort::ParseStrings(const string& comma_sep_addrs, uint16_t default_port, vector<HostPort>* res) { + res->clear(); + vector<string> addr_strings = strings::Split(comma_sep_addrs, ",", strings::SkipEmpty()); + res->reserve(addr_strings.size()); for (const string& addr_string : addr_strings) { HostPort host_port; RETURN_NOT_OK(host_port.ParseString(addr_string, default_port)); - res->push_back(host_port); + res->emplace_back(host_port); + } + return Status::OK(); +} + +Status HostPort::ParseStringsWithScheme(const string& comma_sep_addrs, + uint16_t default_port, + vector<HostPort>* res) { + res->clear(); + + vector<string> addr_strings = strings::Split(comma_sep_addrs, ",", strings::SkipEmpty()); + res->reserve(addr_strings.size()); + for (const string& addr_string : addr_strings) { + HostPort host_port; + RETURN_NOT_OK(host_port.ParseStringWithScheme(addr_string, default_port)); + res->emplace_back(host_port); } return Status::OK(); } http://git-wip-us.apache.org/repos/asf/kudu/blob/32a4fe16/src/kudu/util/net/net_util.h ---------------------------------------------------------------------- diff --git a/src/kudu/util/net/net_util.h b/src/kudu/util/net/net_util.h index c471ae8..329c9f6 100644 --- a/src/kudu/util/net/net_util.h +++ b/src/kudu/util/net/net_util.h @@ -39,10 +39,20 @@ class HostPort { return !host_.empty(); } - // Parse a "host:port" pair into this object. + // Parse a <host>:<port> pair into this object. // If there is no port specified in the string, then 'default_port' is used. + // + // Note that <host> cannot be in IPv6 address notation. Status ParseString(const std::string& str, uint16_t default_port); + // Similar to above but allow the address to have scheme and path, e.g. + // <host> + // <host>:<port> + // <fs>://<host>:<port>/<path> + // + // Note that both scheme and path are ignored. + Status ParseStringWithScheme(const std::string& str, uint16_t default_port); + // Resolve any addresses corresponding to this host:port pair. // Note that a host may resolve to more than one IP address. // @@ -67,6 +77,11 @@ class HostPort { static Status ParseStrings( const std::string& comma_sep_addrs, uint16_t default_port, std::vector<HostPort>* res); + // Similar to above but allow the addresses to have scheme and path, + // which are ignored. + static Status ParseStringsWithScheme( + const std::string& comma_sep_addrs, uint16_t default_port, std::vector<HostPort>* res); + // Takes a vector of HostPort objects and returns a comma separated // string containing of "host:port" pairs. This method is the // "inverse" of ParseStrings().