2 * Copyright 2013 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "folly/Uri.h"
20 #include <boost/regex.hpp>
26 fbstring submatch(const boost::cmatch& m, size_t idx) {
28 return fbstring(sub.first, sub.second);
31 template <class String>
32 void toLower(String& s) {
40 Uri::Uri(StringPiece str) : port_(0) {
41 static const boost::regex uriRegex(
42 "([a-zA-Z][a-zA-Z0-9+.-]*):" // scheme:
43 "([^?#]*)" // authority and path
44 "(?:\\?([^#]*))?" // ?query
45 "(?:#(.*))?"); // #fragment
46 static const boost::regex authorityAndPathRegex("//([^/]*)(/.*)?");
49 if (UNLIKELY(!boost::regex_match(str.begin(), str.end(), match, uriRegex))) {
50 throw std::invalid_argument("invalid URI");
53 scheme_ = submatch(match, 1);
56 StringPiece authorityAndPath(match[2].first, match[2].second);
57 boost::cmatch authorityAndPathMatch;
58 if (!boost::regex_match(authorityAndPath.begin(),
59 authorityAndPath.end(),
60 authorityAndPathMatch,
61 authorityAndPathRegex)) {
62 // Does not start with //, doesn't have authority
63 path_ = authorityAndPath.fbstr();
65 static const boost::regex authorityRegex(
66 "(?:([^@:]*)(?::([^@]*))?@)?" // username, password
67 "(\\[[^\\]]*\\]|[^\\[:]*)" // host (IP-literal, dotted-IPv4, or
69 "(?::(\\d*))?"); // port
71 auto authority = authorityAndPathMatch[1];
72 boost::cmatch authorityMatch;
73 if (!boost::regex_match(authority.first,
77 throw std::invalid_argument("invalid URI authority");
80 StringPiece port(authorityMatch[4].first, authorityMatch[4].second);
82 port_ = to<uint32_t>(port);
85 username_ = submatch(authorityMatch, 1);
86 password_ = submatch(authorityMatch, 2);
87 host_ = submatch(authorityMatch, 3);
88 path_ = submatch(authorityAndPathMatch, 2);
91 query_ = submatch(match, 3);
92 fragment_ = submatch(match, 4);