You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
5.0 KiB

  1. #pragma once
  2. #include <cstring>
  3. #include <string>
  4. #include <unordered_map>
  5. #include <vector>
  6. /**
  7. * @brief
  8. *
  9. * string input_url = "http://127.0.0.1:40000/path_1/path_2/path_3/foo.git?test=1&test2=3";
  10. * //string input_url = "http://127.0.0.1/path_1/path_2/path_3/foo.git?test=1&test2=3";
  11. * //string input_url = "http://127.0.0.1/path_1/path_2/path_3";
  12. * //string input_url = "/path_1/path_2/path_3/?test=1&test2=3";
  13. * //string input_url = "https://127.0.0.1:40000/path_1/path_2/path_3/foo.git?test=&test2=3";
  14. *
  15. * Usage
  16. * Just include header file.
  17. *
  18. * #include "../src/url_parser.h"
  19. *
  20. * URLParser::HTTP_URL http_url = URLParser::Parse(input_url);
  21. *
  22. * std::cout << "scheme:[" << http_url.scheme << "]" << std::endl;
  23. * std::cout << "host:[" << http_url.host << "]" << std::endl;
  24. * std::cout << "port:[" << http_url.port << "]" << std::endl;
  25. *
  26. * Return
  27. * class URLParser
  28. * {
  29. * public:
  30. * struct HTTP_URL
  31. * {
  32. * string scheme; // Defined porotocol on URL. (http, ssh, ftp... etc.)
  33. * string host; // Host name or ip address.
  34. * string port; // Port
  35. * std::vector<string> path; // It contains path information that partitioned. (path_1, path_2...)
  36. * string query_string; // Full of query string.
  37. * std::unordered_map<string, string> query; // It conatains query information. That made up of key, value pair.
  38. * };
  39. * }
  40. *
  41. */
  42. namespace iflytop {
  43. using namespace std;
  44. class URLParserFunction {
  45. public:
  46. static bool FindKeyword(const string& input_url, size_t& st, size_t& before, const string& delim, string& result) {
  47. char temp[1024] = {
  48. 0,
  49. };
  50. size_t temp_st = st;
  51. memcpy(&temp_st, &st, sizeof(temp_st));
  52. st = input_url.find(delim, before);
  53. if (st == string::npos) {
  54. st = temp_st;
  55. return false;
  56. }
  57. memcpy(&temp[0], &input_url[before], st - before);
  58. before = st + delim.length();
  59. result = string(temp);
  60. // if (result.empty()) return false;
  61. return true;
  62. };
  63. static bool SplitQueryString(const string& str, const string& delim, string& key, string& value) {
  64. char first[1024] = {
  65. 0,
  66. };
  67. char second[1024] = {
  68. 0,
  69. };
  70. size_t st = str.find(delim, 0);
  71. memcpy(first, &str[0], st);
  72. memcpy(second, &str[st + 1], str.length() - st);
  73. key = string(first);
  74. value = string(second);
  75. return true;
  76. };
  77. };
  78. class HTTP_URL {
  79. public:
  80. string raw;
  81. string scheme;
  82. string host;
  83. string port;
  84. std::vector<string> path;
  85. string query_string;
  86. std::unordered_map<string, string> query;
  87. string getPath() {
  88. string path;
  89. for (auto& p : this->path) {
  90. path += "/";
  91. path += p;
  92. }
  93. return path;
  94. }
  95. void dump() {
  96. printf("raw:%s\n", raw.c_str());
  97. printf("scheme:%s\n", scheme.c_str());
  98. printf("host:%s\n", host.c_str());
  99. printf("port:%s\n", port.c_str());
  100. printf("path:%s\n", getPath().c_str());
  101. printf("query_string:%s\n", query_string.c_str());
  102. for (auto& q : query) {
  103. printf("query:%s=%s\n", q.first.c_str(), q.second.c_str());
  104. }
  105. printf("=\n");
  106. }
  107. };
  108. class URLParser {
  109. public:
  110. static HTTP_URL Parse(const string& input_url) {
  111. HTTP_URL http_url;
  112. http_url.raw = input_url;
  113. size_t st = 0;
  114. size_t before = 0;
  115. URLParserFunction::FindKeyword(input_url, st, before, "://", http_url.scheme);
  116. URLParserFunction::FindKeyword(input_url, st, before, "/", http_url.host);
  117. size_t temp_st = 0;
  118. size_t temp_before = 0;
  119. string temp_ip;
  120. string temp_port;
  121. if (true == URLParserFunction::FindKeyword(http_url.host, temp_st, temp_before, ":", temp_ip)) {
  122. http_url.port = string(&http_url.host[temp_before]);
  123. http_url.host = temp_ip;
  124. }
  125. while (true) {
  126. string path;
  127. if (false == URLParserFunction::FindKeyword(input_url, st, before, "/", path)) break;
  128. http_url.path.push_back(path);
  129. }
  130. string path;
  131. if (false == URLParserFunction::FindKeyword(input_url, st, before, "?", path)) {
  132. path = string(&input_url[st + 1]);
  133. http_url.path.push_back(path);
  134. return http_url;
  135. }
  136. http_url.path.push_back(path);
  137. if (st < input_url.length()) {
  138. http_url.query_string = string(&input_url[st + 1]);
  139. if (false == http_url.query_string.empty()) {
  140. string query;
  141. st = 0;
  142. before = 0;
  143. while (true) {
  144. string key, value;
  145. if (false == URLParserFunction::FindKeyword(http_url.query_string, st, before, "&", query)) {
  146. URLParserFunction::SplitQueryString(string(&http_url.query_string[before]), "=", key, value);
  147. http_url.query.insert(std::unordered_map<string, string>::value_type(key, value));
  148. break;
  149. }
  150. URLParserFunction::SplitQueryString(query, "=", key, value);
  151. http_url.query.insert(std::unordered_map<string, string>::value_type(key, value));
  152. }
  153. }
  154. }
  155. return http_url;
  156. };
  157. };
  158. } // namespace iflytop