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
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
|