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

#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