diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..ceae7e7 --- /dev/null +++ b/.vscode/tasks.json @@ -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" +} \ No newline at end of file diff --git a/lib/api.hpp b/lib/api.hpp index 059d321..2f19b25 100644 --- a/lib/api.hpp +++ b/lib/api.hpp @@ -5,39 +5,40 @@ #include #include #include -#include + +#include "http.hpp" using namespace std; +class http_request; +class http_response; + + class defapi { public: - vector options; + vector methods; + vector paths; vector keys; - map> val_matrix; - defapi(const vector _options, const vector _keys); - void necessary(const string _option, const vector _keys); - + defapi(const vector _methods, const vector _paths, const vector _keys); + void necessary(const string _path, const vector _keys); }; class api { public: - defapi *def; + defapi* def; - string option; - map object; + string method; + string path; + map params; + string url; string body; - api(defapi *_def, const string _option, const map _object); - api(defapi *_def, const string _body); - - private: + api(defapi* _def, const string _method, const string _path, const map _params = {}, const string _body = {}); + api(defapi* _def, const http_request _req); bool validate(); - void parse(); // čitaj api - void format(); // šalji api - // ~api(); }; #endif diff --git a/lib/http.hpp b/lib/http.hpp new file mode 100644 index 0000000..6c65132 --- /dev/null +++ b/lib/http.hpp @@ -0,0 +1,61 @@ +#ifndef _HTTP_ +#define _HTTP_ + +#include +#include +#include + +#include "api.hpp" + +using namespace std; + + +class defapi; +class api; + +class http_request { + public: + string method; + string url; + map 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 _headers); + void parse(); + void mold(); + +}; + + +class http_response { + public: + string status; + map 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 _headers); + + void mold(); // za slanje + void parse(); // čitaj http +}; + +#endif diff --git a/src/api.cpp b/src/api.cpp index ed08767..e8cbb48 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -1,94 +1,82 @@ #include "../lib/api.hpp" -defapi::defapi(const vector _options, const vector _keys) { - options = _options; +defapi::defapi(const vector _methods, const vector _paths, const vector _keys) { + methods = _methods; + paths = _paths; keys = _keys; } -void defapi::necessary(const string _option, const vector _keys) { - val_matrix[_option].insert( val_matrix[_option].end(), _keys.begin(), _keys.end()); +void defapi::necessary(const string _path, const vector _keys) { + val_matrix[_path].insert( val_matrix[_path].end(), _keys.begin(), _keys.end()); } -api::api(defapi *_def, const string _option, const map _object) { +// radi +api::api(defapi* _def, const string _method, const string _path, const map _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; ival_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; ikeys.size(); i++) { - if (!object[def->keys[i]].empty()) { - body += def->keys[i] + "=" + object[def->keys[i]] + "&"; + // api validacija ključeva + for (uint i=0; ival_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; } + diff --git a/src/http.cpp b/src/http.cpp new file mode 100644 index 0000000..9d523eb --- /dev/null +++ b/src/http.cpp @@ -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 _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")); + +} \ No newline at end of file diff --git a/test/test.cpp b/test/test.cpp index 5084d54..5b850ae 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -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; } diff --git a/test/test.o b/test/test.o index 52da175..430a4ce 100755 Binary files a/test/test.o and b/test/test.o differ