#pragma once //major minor patch #define LITTLESNITCH_VERSION 100 #include #include #include #include #include #include #include #include using json = nlohmann::json; template bool json_get(json j, T& value, K key) noexcept { try { j[key].get_to(value); return true; } catch (nlohmann::detail::type_error& err) { std::cout << "key " << key << " error " << err.what(); } catch (nlohmann::detail::out_of_range& err) { std::cout << "key " << key << " error " << err.what(); } catch (nlohmann::detail::other_error& err) { std::cout << "key " << key << " error " << err.what(); } return false; } template bool json_get(json j, T& value, K key, Ks... keys) noexcept { try { return json_get(j[key], value, keys...); } catch (nlohmann::detail::type_error& err) { std::cout << "key " << key << " error " << err.what(); } catch (nlohmann::detail::out_of_range& err) { std::cout << "key " << key << " error " << err.what(); } catch (nlohmann::detail::other_error& err) { std::cout << "key " << key << " error " << err.what(); } return false; } //! represents one item in the http history. struct HistoryItem { int id = -1; double timestamp = 0; std::string method; std::string scheme; std::string host; unsigned short port = 0; std::string path; int status_code = 0; std::string reason; double rtt = 0.0; size_t size = 0; std::string request_http_version; std::map request_headers; std::string request_content; std::string response_http_version; std::map response_headers; std::string response_content; }; namespace http { struct Request { std::string server_ip_address; bool tls; std::string content; std::string scheme; std::string method; std::string host; unsigned short port; std::string http_version; std::string path; double timestamp_start; double timestamp_end; std::vector> headers; std::string error; }; struct Response { int status_code; std::string http_version; std::string reason; std::string content; double timestamp_start; double timestamp_end; std::vector> headers; }; struct Flow { std::string uid; Request request; Response response; }; inline void to_json(json& j, const Flow& flow) {} inline void from_json(const json& j, Flow& flow) { //std::cout << std::setw(4) << j << "\n\n"; json j_flow; if(!json_get(j, j_flow, "flow")) { return; } json_get(j_flow, flow.uid, "id"); if(json j_request; json_get(j_flow, j_request, "request")) { json_get(j_request, flow.request.tls, "server_conn", "tls_established"); json_get(j_request, flow.request.port, "port"); json_get(j_request, flow.request.host, "host"); json_get(j_request, flow.request.scheme, "scheme"); json_get(j_request, flow.request.path, "path"); json_get(j_request, flow.request.content, "content"); json_get(j_request, flow.request.method, "method"); json_get(j_request, flow.request.http_version, "http_version"); json_get(j_request, flow.request.timestamp_start, "timestamp_start"); json_get(j_request, flow.request.timestamp_end, "timestamp_end"); json j_headers; if(json_get(j_request, j_headers, "headers")) { for(auto& [k,v] : j_headers.items()) { flow.request.headers.push_back(std::make_tuple(v.at(0), v.at(1))); } } } if(json j_response; json_get(j_flow, j_response, "response")) { json_get(j_response, flow.response.status_code, "status_code"); json_get(j_response, flow.response.http_version, "http_version"); json_get(j_response, flow.response.reason, "reason"); json_get(j_response, flow.response.content, "content"); json_get(j_response, flow.response.timestamp_start, "timestamp_start"); json_get(j_response, flow.response.timestamp_end, "timestamp_end"); json j_headers; if(json_get(j_response, j_headers, "headers")) { for(auto& [k,v] : j_headers.items()) { flow.response.headers.push_back(std::make_tuple(v.at(0), v.at(1))); } } } } } Q_DECLARE_METATYPE(http::Flow)