|
|
#pragma once
#include <cstring>
#include <string>
#include <unordered_map>
#include <vector>
/**
* @brief * * string input_url = "http://127.0.0.1:40000/path_1/path_2/path_3/foo.git?test=1&test2=3"; * //string input_url = "http://127.0.0.1/path_1/path_2/path_3/foo.git?test=1&test2=3";
* //string input_url = "http://127.0.0.1/path_1/path_2/path_3";
* //string input_url = "/path_1/path_2/path_3/?test=1&test2=3";
* //string input_url = "https://127.0.0.1:40000/path_1/path_2/path_3/foo.git?test=&test2=3";
* * Usage * Just include header file. * * #include "../src/url_parser.h" * * URLParser::HTTP_URL http_url = URLParser::Parse(input_url); * * std::cout << "scheme:[" << http_url.scheme << "]" << std::endl; * std::cout << "host:[" << http_url.host << "]" << std::endl; * std::cout << "port:[" << http_url.port << "]" << std::endl; * * Return * class URLParser * { * public: * struct HTTP_URL * { * string scheme; // Defined porotocol on URL. (http, ssh, ftp... etc.)
* string host; // Host name or ip address.
* string port; // Port
* std::vector<string> path; // It contains path information that partitioned. (path_1, path_2...)
* string query_string; // Full of query string.
* std::unordered_map<string, string> query; // It conatains query information. That made up of key, value pair.
* }; * } * */
namespace iflytop { using namespace std; class URLParserFunction { public: static bool FindKeyword(const string& input_url, size_t& st, size_t& before, const string& delim, string& result) { char temp[1024] = { 0, }; size_t temp_st = st; memcpy(&temp_st, &st, sizeof(temp_st));
st = input_url.find(delim, before); if (st == string::npos) { st = temp_st; return false; }
memcpy(&temp[0], &input_url[before], st - before); before = st + delim.length();
result = string(temp); // if (result.empty()) return false;
return true; };
static bool SplitQueryString(const string& str, const string& delim, string& key, string& value) { char first[1024] = { 0, }; char second[1024] = { 0, };
size_t st = str.find(delim, 0);
memcpy(first, &str[0], st); memcpy(second, &str[st + 1], str.length() - st);
key = string(first); value = string(second);
return true; }; };
class HTTP_URL { public: string raw; string scheme; string host; string port; std::vector<string> path; string query_string; std::unordered_map<string, string> query;
string getPath() { string path; for (auto& p : this->path) { path += "/"; path += p; } return path; }
void dump() { printf("raw:%s\n", raw.c_str()); printf("scheme:%s\n", scheme.c_str()); printf("host:%s\n", host.c_str()); printf("port:%s\n", port.c_str()); printf("path:%s\n", getPath().c_str()); printf("query_string:%s\n", query_string.c_str()); for (auto& q : query) { printf("query:%s=%s\n", q.first.c_str(), q.second.c_str()); } printf("=\n"); } };
class URLParser { public: static HTTP_URL Parse(const string& input_url) { HTTP_URL http_url; http_url.raw = input_url;
size_t st = 0; size_t before = 0;
URLParserFunction::FindKeyword(input_url, st, before, "://", http_url.scheme); URLParserFunction::FindKeyword(input_url, st, before, "/", http_url.host);
size_t temp_st = 0; size_t temp_before = 0; string temp_ip; string temp_port;
if (true == URLParserFunction::FindKeyword(http_url.host, temp_st, temp_before, ":", temp_ip)) { http_url.port = string(&http_url.host[temp_before]); http_url.host = temp_ip; }
while (true) { string path; if (false == URLParserFunction::FindKeyword(input_url, st, before, "/", path)) break; http_url.path.push_back(path); }
string path; if (false == URLParserFunction::FindKeyword(input_url, st, before, "?", path)) { path = string(&input_url[st + 1]); http_url.path.push_back(path); return http_url; } http_url.path.push_back(path);
if (st < input_url.length()) { http_url.query_string = string(&input_url[st + 1]); if (false == http_url.query_string.empty()) { string query; st = 0; before = 0;
while (true) { string key, value;
if (false == URLParserFunction::FindKeyword(http_url.query_string, st, before, "&", query)) { URLParserFunction::SplitQueryString(string(&http_url.query_string[before]), "=", key, value); http_url.query.insert(std::unordered_map<string, string>::value_type(key, value)); break; }
URLParserFunction::SplitQueryString(query, "=", key, value); http_url.query.insert(std::unordered_map<string, string>::value_type(key, value)); } } }
return http_url; }; }; } // namespace iflytop
|