Http request, response and parser

dev
marcelb 1 year ago
parent de2ba47180
commit 8f6881af92
  1. 29
      .vscode/tasks.json
  2. 33
      lib/api.hpp
  3. 61
      lib/http.hpp
  4. 118
      src/api.cpp
  5. 132
      src/http.cpp
  6. 42
      test/test.cpp
  7. BIN
      test/test.o

29
.vscode/tasks.json vendored

@ -0,0 +1,29 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ build active file",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${fileDirname}/test.cpp",
"${fileDirname}/../src/*.cpp",
"-o",
"${fileDirname}/test.o"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

@ -5,39 +5,40 @@
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include "http.hpp"
using namespace std;
class http_request;
class http_response;
class defapi {
public:
vector<string> options;
vector<string> methods;
vector<string> paths;
vector<string> keys;
map<string, vector<string>> val_matrix;
defapi(const vector<string> _options, const vector<string> _keys);
void necessary(const string _option, const vector<string> _keys);
defapi(const vector<string> _methods, const vector<string> _paths, const vector<string> _keys);
void necessary(const string _path, const vector<string> _keys);
};
class api {
public:
defapi *def;
defapi* def;
string option;
map<string, string> object;
string method;
string path;
map<string, string> params;
string url;
string body;
api(defapi *_def, const string _option, const map<string, string> _object);
api(defapi *_def, const string _body);
private:
api(defapi* _def, const string _method, const string _path, const map<string, string> _params = {}, const string _body = {});
api(defapi* _def, const http_request _req);
bool validate();
void parse(); // čitaj api
void format(); // šalji api
// ~api();
};
#endif

@ -0,0 +1,61 @@
#ifndef _HTTP_
#define _HTTP_
#include <iostream>
#include <string>
#include <map>
#include "api.hpp"
using namespace std;
class defapi;
class api;
class http_request {
public:
string method;
string url;
map<string, string> headers;
string body;
string raw;
// konstruktori zahtjeva
// odlazni
http_request(const string _method, const string _url, const string _body = "");
http_request(const api *_api);
//dolazni
http_request(const string _raw);
//bool validate();
void putheader(const string _key, const string _value);
void putheaders(const map<string, string> _headers);
void parse();
void mold();
};
class http_response {
public:
string status;
map<string, string> headers;
string body;
string raw;
//konstruktor odgovora
// odlazni
void send(const string _body);
// dolaznih
void get(const string _raw);
//bool validate();
void putheader(const string _key, const string _value);
void putheaders(const map<string, string> _headers);
void mold(); // za slanje
void parse(); // čitaj http
};
#endif

@ -1,94 +1,82 @@
#include "../lib/api.hpp"
defapi::defapi(const vector<string> _options, const vector<string> _keys) {
options = _options;
defapi::defapi(const vector<string> _methods, const vector<string> _paths, const vector<string> _keys) {
methods = _methods;
paths = _paths;
keys = _keys;
}
void defapi::necessary(const string _option, const vector<string> _keys) {
val_matrix[_option].insert( val_matrix[_option].end(), _keys.begin(), _keys.end());
void defapi::necessary(const string _path, const vector<string> _keys) {
val_matrix[_path].insert( val_matrix[_path].end(), _keys.begin(), _keys.end());
}
api::api(defapi *_def, const string _option, const map<string, string> _object) {
// radi
api::api(defapi* _def, const string _method, const string _path, const map<string, string> _params, const string _body) {
def = _def;
object = _object;
option = _option;
if (!validate()) {
cout << "Validate API error" << endl;
method = _method;
path = _path;
url = path;
if (!_params.empty()) {
url += '?';
for (auto i : _params) {
url += i.first + '=' + i.second + '&';
}
url.pop_back();
}
format();
}
api::api(defapi *_def, const string _body) {
def = _def;
body = _body;
parse();
if (!validate()) {
cout << "Validate API error" << endl;
cout << "Nije ispravan API" << endl;
}
}
bool api::validate() {
bool isValidate = true;
for (uint i=0; i<def->val_matrix[option].size(); i++) {
def->val_matrix[option][i];
if (object[def->val_matrix[option][i]].empty()) {
isValidate = false;
break;
// radi
api::api(defapi* _def, const http_request _req) {
def = _def;
method = _req.method;
//path = _path;
url = _req.url;
if ( (size_t)url.find("?") < (size_t)url.length() ) {
path = url.substr(0, url.find("?"));
string str_params = url.substr(url.find("?")+1, url.length()-url.find("?")-1);
while (!str_params.empty()) {
string key, value;
key = str_params.substr(0, str_params.find('='));
str_params.erase(0, key.length()+1);
value = str_params.substr(0, str_params.find('&'));
str_params.erase(0, value.length()+1);
params.insert(make_pair(key, value));
}
}
else {
path = url;
}
return isValidate;
}
void api::parse() {
body = _req.body;
// Extract the query string from the API request
size_t queryStart = body.find('?');
size_t protocolEnd = body.find("HTTP/");
if (queryStart == string::npos || (protocolEnd != string::npos && queryStart > protocolEnd)) {
// cout << "No object found in the API request." << endl;
return;
}
// if (!validate()) {
// cout << "Nije ispravan API" << endl;
// }
size_t queryStringStart = (queryStart != string::npos) ? queryStart + 1 : 0;
string queryString = body.substr(queryStringStart, protocolEnd - queryStringStart);
// Parse the query string and extract key-value pairs
istringstream iss(queryString);
string parameter;
while (getline(iss, parameter, '&')) {
size_t equalSignPos = parameter.find('=');
if (equalSignPos != string::npos) {
string key = parameter.substr(0, equalSignPos);
string value = parameter.substr(equalSignPos + 1);
object[key] = value;
}
}
}
void api::format() {
body = "GET /";
if (!option.empty()) {
body += option + '/';
}
body += '?';
bool api::validate() {
bool isValidate = true;
for (uint i=0; i<def->keys.size(); i++) {
if (!object[def->keys[i]].empty()) {
body += def->keys[i] + "=" + object[def->keys[i]] + "&";
// api validacija ključeva
for (uint i=0; i<def->val_matrix[path].size(); i++) {
def->val_matrix[path][i];
if (params[def->val_matrix[path][i]].empty()) {
isValidate = false;
break;
}
}
body.pop_back();
body += " HTTP/1.1";
return isValidate;
}

@ -0,0 +1,132 @@
#include "../lib/http.hpp"
// radi
http_request::http_request(const string _method, const string _url, const string _body) {
method = _method;
url = _url;
body = _body;
mold();
}
// radi
http_request::http_request(const api *_api) {
method = _api->method;
url = _api->url;
body = _api->body;
mold();
}
// radi
http_request::http_request(const string _raw) {
raw = _raw;
parse();
}
// radi
void http_request::parse() {
method = raw.substr(0, raw.find(" "));
url = raw.substr(raw.find("/"), raw.find("HTTP/")-raw.find("/"));
string _headers = raw.substr(raw.find("\r\n")+2, raw.find("\r\n\r\n")-raw.find("\r\n"));
while (!_headers.empty()) {
string key, value;
key = _headers.substr(0, _headers.find(": "));
_headers.erase(0, key.length()+2);
value = _headers.substr(0, _headers.find("\r\n"));
_headers.erase(0, value.length()+2);
headers.insert(make_pair(key, value));
}
// ne radi za specijalan slučaj kada nema zaglavlja
if ((size_t)raw.find("\r\n\r\n") == (size_t)raw.find("\r\n"))
body = raw.substr(raw.find("\r\n\r\n")+4, raw.length()-raw.find("\r\n\r\n"));
else if ((size_t)raw.find("\r\n\r\n") < raw.length())
body = raw.substr(raw.find("\r\n\r\n")+4, raw.find("\r\n")-raw.find("\r\n\r\n"));
}
void http_request::putheader(const string _key, const string _value) {
headers[_key] = _value;
mold();
}
void http_request::putheaders(const map<string, string> _headers) {
headers = _headers;
mold();
}
/**
* http zahtjev formiranje raw
*/
// radi
void http_request::mold() {
raw = method.empty() ? "GET" : method;
raw += " " + url + " HTTP/1.1\r\n";
if (!headers.empty()) {
for (auto i : headers) {
raw += i.first + ": " + i.second + "\r\n";
}
}
raw += "\r\n" + body;
}
void http_response::send(const string _body) {
body = _body;
mold();
}
void http_response::get(const string _raw) {
raw = _raw;
parse();
}
/**
* Nakon
*/
void http_response::mold() {
raw = "HTTP/1.1 200 OK\r\n";
if (!headers.empty()) {
raw += '?';
for (auto i : headers) {
raw += i.first + ": " + i.second + "\r\n";
}
}
raw += "\r\n" + body;
}
// radi
void http_response::parse() {
string protocol = raw.substr(0, raw.find(" "));
status = raw.substr(raw.find(" ")+1, raw.find(" ",raw.find(" ")+1)-raw.find(" ")-1);
if ((size_t)raw.find("\r\n") < raw.length()) {
string _headers = raw.substr(raw.find("\r\n")+2, raw.find("\r\n\r\n")-raw.find("\r\n"));
while (!_headers.empty()) {
string key, value;
key = _headers.substr(0, _headers.find(": "));
_headers.erase(0, key.length()+2);
value = _headers.substr(0, _headers.find("\r\n"));
_headers.erase(0, value.length()+2);
headers.insert(make_pair(key, value));
}
}
// ne radi za specijalan slučaj kada nema zaglavlja
if ((size_t)raw.find("\r\n\r\n") == (size_t)raw.find("\r\n"))
body = raw.substr(raw.find("\r\n\r\n")+4, raw.length()-raw.find("\r\n\r\n"));
else if ((size_t)raw.find("\r\n\r\n") < raw.length())
body = raw.substr(raw.find("\r\n\r\n")+4, raw.find("\r\n")-raw.find("\r\n\r\n"));
}

@ -6,20 +6,42 @@ using namespace std;
int main() {
defapi myDef({"add", "delete", "update"}, {"id", "key", "value"});
defapi myApi({"GET"}, {"add", "delete", "update"}, {"id", "key", "value"});
myApi.necessary("add", {"id", "key", "value"});
myApi.necessary("delete", {"id"});
myApi.necessary("update", {"id"});
myApi.necessary("update", {"value"});
// cout << myDef.keys[2];
// api uf(&myApi, "GET", "/delete", {{"id", "4"}}, "bay");
myDef.necessary("add", {"id", "key", "value"});
myDef.necessary("delete", {"id"});
myDef.necessary("update", {"id"});
myDef.necessary("update", {"value"});
// cout << myDef.val_matrix["delete"].empty();
// http myHttp(&myApi, "GET /fghfhf HTTP/1.1\r\nBaba");
// //http myHttp(&myApi, "GET /hello/?id=4&post=99 HTTP/1.1\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)\r\nHost: www.tutorialspoint.com\r\nAccept-Language: en-us\r\nAccept-Encoding: gzip, deflate\r\nConnection: Keep-Alive\r\n\r\nHELLO WORLD\r\n");
api myApi(&myDef, "GET /update/?id=1&value=tru eHTTP/1.1\n");
cout << myApi.object["value"];
//cout << myHttp.rawall;
// http_request mojzahtjev("GET", "/baba/maloroga?value1=54", "good" );
// mojzahtjev.putheader("Content-type", "text/plain");
// cout << mojzahtjev.method << " " << mojzahtjev.url << endl << mojzahtjev.raw;
// http_request myres(&uf);
// myres.putheader("Content-type", "text/plain");
http_request myres("GET /delete?id=4 HTTP/1.1\r\nContent-type: text/plain\r\n\n\rBAY");
// myres.get("HTTP/1.1 200 OK\r\n\r\nnotauth");
// myres.get("HTTP/1.1 200 OK");
api uf(&myApi, myres);
cout << uf.method << " " << uf.path << " " << uf.body << endl;// << myres.raw;
// cout << myres.method << " " << myres.url << " " << myres.body << endl;// << myres.raw;
for(auto i : uf.params)
cout << i.first << " " << i.second << endl;
}

Binary file not shown.
Loading…
Cancel
Save