X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FUri.cpp;h=bc94a31fb33a6cd688225ee97e9354eee6f5dffd;hb=dc93938852aa64604563afbc8d185062f01153f2;hp=a94c9308fb0f84fa3445bb435209d5a24b94fd28;hpb=4c787a9d2f0ce748d7082fd1a6469f7ed6999dc6;p=folly.git diff --git a/folly/Uri.cpp b/folly/Uri.cpp index a94c9308..bc94a31f 100644 --- a/folly/Uri.cpp +++ b/folly/Uri.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2016 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "folly/Uri.h" +#include #include #include @@ -37,7 +37,7 @@ void toLower(String& s) { } // namespace -Uri::Uri(StringPiece str) : port_(0) { +Uri::Uri(StringPiece str) : hasAuthority_(false), port_(0) { static const boost::regex uriRegex( "([a-zA-Z][a-zA-Z0-9+.-]*):" // scheme: "([^?#]*)" // authority and path @@ -47,7 +47,7 @@ Uri::Uri(StringPiece str) : port_(0) { boost::cmatch match; if (UNLIKELY(!boost::regex_match(str.begin(), str.end(), match, uriRegex))) { - throw std::invalid_argument("invalid URI"); + throw std::invalid_argument(to("invalid URI ", str)); } scheme_ = submatch(match, 1); @@ -60,12 +60,13 @@ Uri::Uri(StringPiece str) : port_(0) { authorityAndPathMatch, authorityAndPathRegex)) { // Does not start with //, doesn't have authority + hasAuthority_ = false; path_ = authorityAndPath.fbstr(); } else { static const boost::regex authorityRegex( "(?:([^@:]*)(?::([^@]*))?@)?" // username, password - "(\\[[^\\]]*\\]|[^\\[:]*)" // host (IP-literal, dotted-IPv4, or - // named host) + "(\\[[^\\]]*\\]|[^\\[:]*)" // host (IP-literal (e.g. '['+IPv6+']', + // dotted-IPv4, or named host) "(?::(\\d*))?"); // port auto authority = authorityAndPathMatch[1]; @@ -74,7 +75,9 @@ Uri::Uri(StringPiece str) : port_(0) { authority.second, authorityMatch, authorityRegex)) { - throw std::invalid_argument("invalid URI authority"); + throw std::invalid_argument( + to("invalid URI authority ", + StringPiece(authority.first, authority.second))); } StringPiece port(authorityMatch[4].first, authorityMatch[4].second); @@ -82,6 +85,7 @@ Uri::Uri(StringPiece str) : port_(0) { port_ = to(port); } + hasAuthority_ = true; username_ = submatch(authorityMatch, 1); password_ = submatch(authorityMatch, 2); host_ = submatch(authorityMatch, 3); @@ -92,4 +96,66 @@ Uri::Uri(StringPiece str) : port_(0) { fragment_ = submatch(match, 4); } +fbstring Uri::authority() const { + fbstring result; + + // Port is 5 characters max and we have up to 3 delimiters. + result.reserve(host().size() + username().size() + password().size() + 8); + + if (!username().empty() || !password().empty()) { + result.append(username()); + + if (!password().empty()) { + result.push_back(':'); + result.append(password()); + } + + result.push_back('@'); + } + + result.append(host()); + + if (port() != 0) { + result.push_back(':'); + toAppend(port(), &result); + } + + return result; +} + +fbstring Uri::hostname() const { + if (host_.size() > 0 && host_[0] == '[') { + // If it starts with '[', then it should end with ']', this is ensured by + // regex + return host_.substr(1, host_.size() - 2); + } + return host_; +} + +const std::vector>& Uri::getQueryParams() { + if (!query_.empty() && queryParams_.empty()) { + // Parse query string + static const boost::regex queryParamRegex( + "(^|&)" /*start of query or start of parameter "&"*/ + "([^=&]*)=?" /*parameter name and "=" if value is expected*/ + "([^=&]*)" /*parameter value*/ + "(?=(&|$))" /*forward reference, next should be end of query or + start of next parameter*/); + boost::cregex_iterator paramBeginItr( + query_.data(), query_.data() + query_.size(), queryParamRegex); + boost::cregex_iterator paramEndItr; + for (auto itr = paramBeginItr; itr != paramEndItr; itr++) { + if (itr->length(2) == 0) { + // key is empty, ignore it + continue; + } + queryParams_.emplace_back( + fbstring((*itr)[2].first, (*itr)[2].second), // parameter name + fbstring((*itr)[3].first, (*itr)[3].second) // parameter value + ); + } + } + return queryParams_; +} + } // namespace folly