From 89a6d9a528be283d27fcdb30f9e05bd3b035b592 Mon Sep 17 00:00:00 2001 From: Nicholas Orlowsky Date: Sat, 14 Oct 2023 19:34:02 -0400 Subject: [PATCH] more benchmarks --- README.md | 2 +- backends/backend.cpp | 2 +- backends/file_backend.cpp | 57 ++++++++++++++++++++++++++++++++++++--- http.cpp | 15 +++++------ main.cpp | 30 ++++++++++++--------- socket.cpp | 2 +- 6 files changed, 82 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 43fcd68..bfdc55e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A simple web server written in C++ ## Module-Based Backends -Anthracite includes (read: will include) a system for allowing different "backend modules" to handle requests. +Anthracite includes (read: will include) system for allowing different "backend modules" to handle requests. This allows for anthracite to be extended for additional use-cases. For example, the following backends could be implemented: diff --git a/backends/backend.cpp b/backends/backend.cpp index d417e28..dfe1071 100644 --- a/backends/backend.cpp +++ b/backends/backend.cpp @@ -2,5 +2,5 @@ class backend { public: - virtual http_response handle_request(http_request req) {}; + virtual http_response handle_request(http_request req) = 0; }; diff --git a/backends/file_backend.cpp b/backends/file_backend.cpp index 8a88ab1..7e10a00 100644 --- a/backends/file_backend.cpp +++ b/backends/file_backend.cpp @@ -1,8 +1,12 @@ #include "backend.cpp" +#include class file_backend : public backend { -public: - http_response handle_request(http_request req) { +private: + unordered_map file_cache; + bool cache_enabled; + + http_response handle_request_nocache(http_request req) { string filename = req.path() == "/" ? "index.html" : req.path(); filename = "./www/" + filename; ifstream stream(filename); @@ -16,6 +20,53 @@ public: stringstream buffer; buffer << stream.rdbuf(); - return http_response(buffer.str(), status); + return { buffer.str(), status }; + } + + http_response handle_request_cache(http_request req) { + string filename = req.path() == "/" ? "/index.html" : req.path(); + filename = "./www" + filename; + auto file_info = file_cache.find(filename); + + int status = 200; + if (file_info == file_cache.end()) { + status = 404; + filename = "./error_pages/404.html"; + file_info = file_cache.find(filename); + } + + return { file_info->second, status }; + } + + void populate_cache_dir(string dir) { + filesystem::recursive_directory_iterator cur = begin(filesystem::recursive_directory_iterator(dir)); + filesystem::recursive_directory_iterator fin = end(filesystem::recursive_directory_iterator(dir)); + + while (cur != fin) { + auto p = cur->path(); + string filename = p.string(); + stringstream buffer; + ifstream stream(filename); + buffer << stream.rdbuf(); + file_cache[filename] = buffer.str(); + cout << "File at " << filename << " cached (" << file_cache[filename].size() << " bytes)" << endl; + ++cur; + } + } + + void populate_cache() { + populate_cache_dir("./www/"); + populate_cache_dir("./error_pages/"); + } + +public: + file_backend(bool enable_cache) : cache_enabled(enable_cache) { + if(cache_enabled) { + populate_cache(); + } + } + + http_response handle_request(http_request req) override { + return cache_enabled ? handle_request_cache(req) : handle_request_nocache(req); } }; diff --git a/http.cpp b/http.cpp index 31dc6be..ce4a90b 100644 --- a/http.cpp +++ b/http.cpp @@ -142,11 +142,11 @@ static unordered_map const http_status_map = { class name_value { private: - string _name; - string _value; - + string _name; + string _value; + protected: - name_value() {} + name_value() {} public: name_value(string name, string value) @@ -155,11 +155,10 @@ public: { } virtual ~name_value() = default; - name_value(const name_value &) = default; - name_value& operator =(name_value const&) = default; + name_value(const name_value&) = default; + name_value& operator=(name_value const&) = default; name_value(name_value&&) = default; - name_value& operator = (name_value&&) = default; - + name_value& operator=(name_value&&) = default; string name() { return _name; } string value() { return _value; } diff --git a/main.cpp b/main.cpp index fb3d3dd..3208de3 100644 --- a/main.cpp +++ b/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -14,6 +15,15 @@ void log_request_an_response(http_request req, http_response resp); constexpr int default_port = 80; +void handle_client(anthracite_socket s, file_backend fb) +{ + http_request req(s); + http_response resp = fb.handle_request(req); + log_request_an_response(req, resp); + s.send_message(resp.to_string()); + s.close_conn(); +} + int main(int argc, char** argv) { int port_number = default_port; @@ -22,25 +32,21 @@ int main(int argc, char** argv) port_number = atoi(argv[1]); } - cout << "Initializing Anthracite\n"; + cout << "Initializing Anthracite" << endl; anthracite_socket s(port_number); - cout << "Initialization Complete\n"; - cout << "Listening for HTTP connections on port " << port_number << "\n"; - file_backend fb; + file_backend fb(false); + cout << "Initialization Complete" << endl; + cout << "Listening for HTTP connections on port " << port_number << endl; - while (true) { + while(true) { s.wait_for_conn(); - http_request req(s); - http_response resp = fb.handle_request(req); - log_request_an_response(req, resp); - s.send_message(resp.to_string()); - s.close_conn(); + thread(handle_client, s, ref(fb)).detach(); } - return 0; + exit(0); } void log_request_an_response(http_request req, http_response resp) { - cout << "[" << resp.status_code() << " " + http_status_map.find(resp.status_code())->second + "] " + req.client_ip() + " " + http_reverse_method_map.find(req.method())->second + " " + req.path() + "\n"; + cout << "[" << resp.status_code() << " " + http_status_map.find(resp.status_code())->second + "] " + req.client_ip() + " " + http_reverse_method_map.find(req.method())->second + " " + req.path() << endl; } diff --git a/socket.cpp b/socket.cpp index ae840be..e0afe17 100644 --- a/socket.cpp +++ b/socket.cpp @@ -20,7 +20,7 @@ private: socklen_t client_addr_len {}; public: - anthracite_socket(int port, int max_queue = 10) + anthracite_socket(int port, int max_queue = 100) : server_socket(socket(AF_INET, SOCK_STREAM, 0)) , client_ip("") {