Url.cc 6.0 KB

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