Url.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * Copyright 1999-2019 Alibaba Cloud All rights reserved.
  3. *
  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
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.
  15. */
  16. #include <algorithm>
  17. #include <alibabacloud/core/Url.h>
  18. #include <sstream>
  19. namespace AlibabaCloud {
  20. namespace {
  21. #define INVALID_PORT -1
  22. } // namespace
  23. Url::Url(const std::string &url)
  24. : scheme_(), userName_(), password_(), host_(), path_(),
  25. port_(INVALID_PORT), query_(), fragment_() {
  26. if (!url.empty())
  27. fromString(url);
  28. }
  29. Url::~Url() {}
  30. bool Url::operator==(const Url &url) const {
  31. return scheme_ == url.scheme_ && userName_ == url.userName_ &&
  32. password_ == url.password_ && host_ == url.host_ &&
  33. path_ == url.path_ && port_ == url.port_ && query_ == url.query_ &&
  34. fragment_ == url.fragment_;
  35. }
  36. bool Url::operator!=(const Url &url) const { return !(*this == url); }
  37. std::string Url::authority() const {
  38. if (!isValid())
  39. return std::string();
  40. std::ostringstream out;
  41. std::string str = userInfo();
  42. if (!str.empty())
  43. out << str << "@";
  44. out << host_;
  45. if (port_ != INVALID_PORT)
  46. out << ":" << port_;
  47. return out.str();
  48. }
  49. void Url::clear() {
  50. scheme_.clear();
  51. userName_.clear();
  52. password_.clear();
  53. host_.clear();
  54. path_.clear();
  55. port_ = INVALID_PORT;
  56. query_.clear();
  57. fragment_.clear();
  58. }
  59. std::string Url::fragment() const { return fragment_; }
  60. void Url::fromString(const std::string &url) {
  61. clear();
  62. if (url.empty())
  63. return;
  64. std::string str = url;
  65. std::string::size_type pos = 0;
  66. std::string authority, fragment, path, query, scheme;
  67. pos = str.find("://");
  68. if (pos != str.npos) {
  69. scheme = str.substr(0, pos);
  70. str.erase(0, pos + 3);
  71. }
  72. pos = str.find('#');
  73. if (pos != str.npos) {
  74. fragment = str.substr(pos + 1);
  75. str.erase(pos);
  76. }
  77. pos = str.find('?');
  78. if (pos != str.npos) {
  79. query = str.substr(pos + 1);
  80. str.erase(pos);
  81. }
  82. pos = str.find('/');
  83. if (pos != str.npos) {
  84. path = str.substr(pos);
  85. str.erase(pos);
  86. } else {
  87. path = "/";
  88. }
  89. authority = str;
  90. setScheme(scheme);
  91. setAuthority(authority);
  92. setPath(path);
  93. setQuery(query);
  94. setFragment(fragment);
  95. }
  96. bool Url::hasFragment() const { return !fragment_.empty(); }
  97. bool Url::hasQuery() const { return !query_.empty(); }
  98. std::string Url::host() const { return host_; }
  99. bool Url::isEmpty() const {
  100. return scheme_.empty() && userName_.empty() && password_.empty() &&
  101. host_.empty() && path_.empty() && (port_ == INVALID_PORT) &&
  102. query_.empty() && fragment_.empty();
  103. }
  104. bool Url::isValid() const {
  105. if (isEmpty())
  106. return false;
  107. if (host_.empty())
  108. return false;
  109. bool valid = true;
  110. if (userName_.empty())
  111. valid = password_.empty();
  112. return valid;
  113. }
  114. int Url::port() const { return port_; }
  115. std::string Url::password() const { return password_; }
  116. std::string Url::path() const { return path_; }
  117. std::string Url::query() const { return query_; }
  118. std::string Url::scheme() const { return scheme_; }
  119. void Url::setAuthority(const std::string &authority) {
  120. if (authority.empty()) {
  121. setUserInfo("");
  122. setHost("");
  123. setPort(INVALID_PORT);
  124. return;
  125. }
  126. std::string userinfo, host, port;
  127. std::string::size_type pos = 0, prevpos = 0;
  128. pos = authority.find('@');
  129. if (pos != authority.npos) {
  130. userinfo = authority.substr(0, pos);
  131. prevpos = pos + 1;
  132. } else {
  133. pos = 0;
  134. }
  135. pos = authority.find(':', prevpos);
  136. if (pos == authority.npos) {
  137. host = authority.substr(prevpos);
  138. } else {
  139. host = authority.substr(prevpos, pos - prevpos);
  140. port = authority.substr(pos + 1);
  141. }
  142. setUserInfo(userinfo);
  143. setHost(host);
  144. setPort(!port.empty() ? atoi(port.c_str()) : INVALID_PORT);
  145. }
  146. void Url::setFragment(const std::string &fragment) { fragment_ = fragment; }
  147. void Url::setHost(const std::string &host) {
  148. if (host.empty()) {
  149. host_.clear();
  150. return;
  151. }
  152. host_ = host;
  153. std::transform(host_.begin(), host_.end(), host_.begin(), ::tolower);
  154. }
  155. void Url::setPassword(const std::string &password) { password_ = password; }
  156. void Url::setPath(const std::string &path) { path_ = path; }
  157. void Url::setPort(int port) { port_ = port; }
  158. void Url::setQuery(const std::string &query) { query_ = query; }
  159. void Url::setScheme(const std::string &scheme) {
  160. if (scheme.empty()) {
  161. scheme_.clear();
  162. return;
  163. }
  164. scheme_ = scheme;
  165. std::transform(scheme_.begin(), scheme_.end(), scheme_.begin(), ::tolower);
  166. }
  167. void Url::setUserInfo(const std::string &userInfo) {
  168. if (userInfo.empty()) {
  169. userName_.clear();
  170. password_.clear();
  171. return;
  172. }
  173. auto pos = userInfo.find(':');
  174. if (pos == userInfo.npos) {
  175. userName_ = userInfo;
  176. } else {
  177. userName_ = userInfo.substr(0, pos);
  178. password_ = userInfo.substr(pos + 1);
  179. }
  180. }
  181. void Url::setUserName(const std::string &userName) { userName_ = userName; }
  182. std::string Url::toString() const {
  183. if (!isValid())
  184. return std::string();
  185. std::ostringstream out;
  186. if (!scheme_.empty())
  187. out << scheme_ << "://";
  188. std::string str = authority();
  189. if (!str.empty())
  190. out << authority();
  191. if (path_.empty())
  192. out << "/";
  193. else
  194. out << path_;
  195. if (hasQuery())
  196. out << "?" << query_;
  197. if (hasFragment())
  198. out << "#" << fragment_;
  199. return out.str();
  200. }
  201. std::string Url::userInfo() const {
  202. if (!isValid())
  203. return std::string();
  204. std::ostringstream out;
  205. out << userName_;
  206. if (!password_.empty())
  207. out << ":" << password_;
  208. return out.str();
  209. }
  210. std::string Url::userName() const { return userName_; }
  211. } // namespace AlibabaCloud