Commit 5b39efc2 authored by Tudor Bosman's avatar Tudor Bosman Committed by Noam Lerner

Fix toString() for authority-less URIs

Summary: Uri("foo:bar").str() would incorrectly return "foo://bar"

Test Plan: test added

Reviewed By: savasp@fb.com, markisaa@fb.com

Subscribers: folly-diffs@, yfeldblum, chalfant

FB internal diff: D2107530

Tasks: 7248055

Signature: t1:2107530:1432837143:c100f148c07b5b141cc036b1b39e6c8317e9bbd6
parent fa248777
...@@ -25,6 +25,7 @@ namespace folly { ...@@ -25,6 +25,7 @@ namespace folly {
template <class String> template <class String>
String Uri::toString() const { String Uri::toString() const {
String str; String str;
if (hasAuthority_) {
toAppend(scheme_, "://", &str); toAppend(scheme_, "://", &str);
if (!password_.empty()) { if (!password_.empty()) {
toAppend(username_, ":", password_, "@", &str); toAppend(username_, ":", password_, "@", &str);
...@@ -35,6 +36,9 @@ String Uri::toString() const { ...@@ -35,6 +36,9 @@ String Uri::toString() const {
if (port_ != 0) { if (port_ != 0) {
toAppend(":", port_, &str); toAppend(":", port_, &str);
} }
} else {
toAppend(scheme_, ":", &str);
}
toAppend(path_, &str); toAppend(path_, &str);
if (!query_.empty()) { if (!query_.empty()) {
toAppend("?", query_, &str); toAppend("?", query_, &str);
......
...@@ -37,7 +37,7 @@ void toLower(String& s) { ...@@ -37,7 +37,7 @@ void toLower(String& s) {
} // namespace } // namespace
Uri::Uri(StringPiece str) : port_(0) { Uri::Uri(StringPiece str) : hasAuthority_(false), port_(0) {
static const boost::regex uriRegex( static const boost::regex uriRegex(
"([a-zA-Z][a-zA-Z0-9+.-]*):" // scheme: "([a-zA-Z][a-zA-Z0-9+.-]*):" // scheme:
"([^?#]*)" // authority and path "([^?#]*)" // authority and path
...@@ -60,6 +60,7 @@ Uri::Uri(StringPiece str) : port_(0) { ...@@ -60,6 +60,7 @@ Uri::Uri(StringPiece str) : port_(0) {
authorityAndPathMatch, authorityAndPathMatch,
authorityAndPathRegex)) { authorityAndPathRegex)) {
// Does not start with //, doesn't have authority // Does not start with //, doesn't have authority
hasAuthority_ = false;
path_ = authorityAndPath.fbstr(); path_ = authorityAndPath.fbstr();
} else { } else {
static const boost::regex authorityRegex( static const boost::regex authorityRegex(
...@@ -84,6 +85,7 @@ Uri::Uri(StringPiece str) : port_(0) { ...@@ -84,6 +85,7 @@ Uri::Uri(StringPiece str) : port_(0) {
port_ = to<uint16_t>(port); port_ = to<uint16_t>(port);
} }
hasAuthority_ = true;
username_ = submatch(authorityMatch, 1); username_ = submatch(authorityMatch, 1);
password_ = submatch(authorityMatch, 2); password_ = submatch(authorityMatch, 2);
host_ = submatch(authorityMatch, 3); host_ = submatch(authorityMatch, 3);
......
...@@ -76,7 +76,10 @@ class Uri { ...@@ -76,7 +76,10 @@ class Uri {
std::string str() const { return toString<std::string>(); } std::string str() const { return toString<std::string>(); }
fbstring fbstr() const { return toString<fbstring>(); } fbstring fbstr() const { return toString<fbstring>(); }
void setPort(uint16_t port) {port_ = port;} void setPort(uint16_t port) {
hasAuthority_ = true;
port_ = port;
}
/** /**
* Get query parameters as key-value pairs. * Get query parameters as key-value pairs.
...@@ -105,6 +108,7 @@ class Uri { ...@@ -105,6 +108,7 @@ class Uri {
fbstring username_; fbstring username_;
fbstring password_; fbstring password_;
fbstring host_; fbstring host_;
bool hasAuthority_;
uint16_t port_; uint16_t port_;
fbstring path_; fbstring path_;
fbstring query_; fbstring query_;
......
...@@ -239,7 +239,7 @@ TEST(Uri, Simple) { ...@@ -239,7 +239,7 @@ TEST(Uri, Simple) {
EXPECT_EQ("/etc/motd", u.path()); EXPECT_EQ("/etc/motd", u.path());
EXPECT_EQ("", u.query()); EXPECT_EQ("", u.query());
EXPECT_EQ("", u.fragment()); EXPECT_EQ("", u.fragment());
EXPECT_EQ("file:///etc/motd", u.fbstr()); EXPECT_EQ("file:/etc/motd", u.fbstr());
} }
{ {
...@@ -389,6 +389,29 @@ TEST(Uri, Simple) { ...@@ -389,6 +389,29 @@ TEST(Uri, Simple) {
// success // success
} }
} }
// No authority (no "//") is valid
{
fbstring s("this:is/a/valid/uri");
Uri u(s);
EXPECT_EQ("this", u.scheme());
EXPECT_EQ("is/a/valid/uri", u.path());
EXPECT_EQ(s, u.fbstr());
}
{
fbstring s("this:is:another:valid:uri");
Uri u(s);
EXPECT_EQ("this", u.scheme());
EXPECT_EQ("is:another:valid:uri", u.path());
EXPECT_EQ(s, u.fbstr());
}
{
fbstring s("this:is@another:valid:uri");
Uri u(s);
EXPECT_EQ("this", u.scheme());
EXPECT_EQ("is@another:valid:uri", u.path());
EXPECT_EQ(s, u.fbstr());
}
} }
/** /**
......
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