From 9add21448795685478919b4d5682d2c26ba43e10 Mon Sep 17 00:00:00 2001 From: Dan Parnham Date: Fri, 12 Jan 2024 13:51:02 +0000 Subject: [PATCH] Fixed bug with the new path-based Response where the headers were not being populated. Moved the examples to source files instead of headers. There's no need for them to be headers since each Module registers itself. --- include/niven/Cookie.h | 2 +- include/niven/Dependencies.h | 81 ------------------- include/niven/Host.h | 1 - src/examples/example.cpp | 51 ++++++------ .../examples/modules/Cookies.cpp | 0 .../examples/modules/Dependencies.cpp | 0 .../examples/modules/Entities.cpp | 0 .../examples/modules/Files.cpp | 0 .../examples/modules/Hashing.cpp | 0 .../examples/modules/Headers.cpp | 0 .../examples/modules/Pipeline.cpp | 0 .../examples/modules/Query.cpp | 0 .../examples/modules/RouteCaptures.cpp | 0 .../examples/modules/Simple.cpp | 0 src/examples/premake5.lua | 4 +- src/examples/ssl.cpp | 32 ++++---- src/niven/Cookie.cpp | 2 +- src/niven/Response.cpp | 61 +++++++------- 18 files changed, 80 insertions(+), 154 deletions(-) delete mode 100644 include/niven/Dependencies.h rename include/examples/Cookies.hpp => src/examples/modules/Cookies.cpp (100%) rename include/examples/Dependencies.hpp => src/examples/modules/Dependencies.cpp (100%) rename include/examples/Entities.hpp => src/examples/modules/Entities.cpp (100%) rename include/examples/Files.hpp => src/examples/modules/Files.cpp (100%) rename include/examples/Hashing.hpp => src/examples/modules/Hashing.cpp (100%) rename include/examples/Headers.hpp => src/examples/modules/Headers.cpp (100%) rename include/examples/Pipeline.hpp => src/examples/modules/Pipeline.cpp (100%) rename include/examples/Query.hpp => src/examples/modules/Query.cpp (100%) rename include/examples/RouteCaptures.hpp => src/examples/modules/RouteCaptures.cpp (100%) rename include/examples/Simple.hpp => src/examples/modules/Simple.cpp (100%) diff --git a/include/niven/Cookie.h b/include/niven/Cookie.h index 1b8032e..3d37013 100644 --- a/include/niven/Cookie.h +++ b/include/niven/Cookie.h @@ -25,7 +25,7 @@ namespace niven Cookie(std::string name, std::string value, const DateTime &expires) : name(name), value(value), expires(expires) {} // Build the cookie string. - std::string Build(); + std::string Build() const; // Enable the Secure flag. Cookie &Secure(); diff --git a/include/niven/Dependencies.h b/include/niven/Dependencies.h deleted file mode 100644 index 5384c94..0000000 --- a/include/niven/Dependencies.h +++ /dev/null @@ -1,81 +0,0 @@ -// #pragma once - -// #include -// #include -// #include -// #include - - -// namespace niven -// { -// // A dependency container implementation with basic functionality. -// class Dependencies -// { -// public: - -// // Register a concrete class type with the container. Instances will be created (using the supplied -// // constructor parameters) each time it is resolved. -// template void Register(Parameters... parameters) -// { -// static_assert(std::is_base_of::value, "Concrete class must be derived from Interface type"); - -// this->containers[typeid(Interface).name()].Set([parameters...]() { return new Concrete(parameters...); }); -// } - - -// // Register a singleton with the container. Any registered singleton must be thread safe since -// // it will be accessed from concurrent request handlers. -// template void Register(std::shared_ptr singleton) -// { -// auto copy = new std::shared_ptr(singleton); - -// this->containers[typeid(Interface).name()].Set([=]() { return copy; }, [=]() { delete copy; }); -// } - - -// // Resolve the required type. Use the same function to retrieve singletons -// // and standard instances alike. -// template std::shared_ptr Resolve() -// { -// auto &con = this->containers[typeid(Interface).name()]; - -// if (con.retrieve) -// { -// return con.dispose -// ? *static_cast *>(con.retrieve()) -// : std::shared_ptr((Interface *)con.retrieve()); -// } - -// return nullptr; -// } - - -// private: - -// // Container for a given base type. It simply contains functions -// // for dependency retrieval and cleaning up. -// struct Container -// { -// std::function retrieve = nullptr; -// std::function dispose = nullptr; // Singleton has a dispose - - -// void Set(std::function retrieve, std::function dispose = nullptr) -// { -// if (this->dispose) this->dispose(); - -// this->retrieve = retrieve; -// this->dispose = dispose; -// } - - -// ~Container() -// { -// if (this->dispose) this->dispose(); -// } -// }; - - -// std::map containers; -// }; -// } diff --git a/include/niven/Host.h b/include/niven/Host.h index d8b6acf..6de3e1b 100644 --- a/include/niven/Host.h +++ b/include/niven/Host.h @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include diff --git a/src/examples/example.cpp b/src/examples/example.cpp index 1bb9616..883ecd8 100644 --- a/src/examples/example.cpp +++ b/src/examples/example.cpp @@ -5,38 +5,39 @@ #include #include +#include -#include "examples/Simple.hpp" -#include "examples/Entities.hpp" -#include "examples/Dependencies.hpp" -#include "examples/Pipeline.hpp" -#include "examples/Cookies.hpp" -#include "examples/Headers.hpp" -#include "examples/Query.hpp" -#include "examples/RouteCaptures.hpp" -#include "examples/Hashing.hpp" -#include "examples/Files.hpp" +// #include "examples/Simple.hpp" +// #include "examples/Entities.hpp" +// #include "examples/Dependencies.hpp" +// #include "examples/Pipeline.hpp" +// #include "examples/Cookies.hpp" +// #include "examples/Headers.hpp" +// #include "examples/Query.hpp" +// #include "examples/RouteCaptures.hpp" +// #include "examples/Hashing.hpp" +// #include "examples/Files.hpp" -using namespace std; -using namespace emg; -using namespace niven; +// using namespace std; +// using namespace emg; +// using namespace niven; bool run = true; -condition_variable condition; +std::condition_variable condition; int main(int argc, char **argv) { // Enable logging to stdout - Log::Initialise({ make_unique() }); - Log::Verbosity("info"); + emg::Log::Initialise({ std::make_unique() }); + emg::Log::Verbosity("info"); // Catch the interrupt/quit signals and handle appropriately signal(SIGINT, [](int) { run = false; condition.notify_one(); }); signal(SIGQUIT, [](int) { run = false; condition.notify_one(); }); - NivenHost host; + niven::NivenHost host; // Configure the host to listen on port 8090 host.Listen(8090); @@ -50,11 +51,11 @@ int main(int argc, char **argv) // Refer to https://github.com/emergent-design/libemergent/ for more // information about the C++ Redis wrappers. This Redis connection is // used in the "include/examples/Dependencies.hpp" example. - host.Register(make_shared()); + host.Register(std::make_shared()); // Resolve the singleton and invoke the Initialise function which will // connect to redis using the default parameters (127.0.0.1:6379). - host.Resolve()->Initialise(); + host.Resolve()->Initialise(); // Start the host running. This function will return true if successfully @@ -62,10 +63,11 @@ int main(int argc, char **argv) // variable to wait for an interrupt or quit signal from the user. if (host.Run()) { - cout << "Listening on port 8090" << endl; + std::cout << "Listening on port 8090\n"; + + std::mutex m; + std::unique_lock lock(m); - mutex m; - unique_lock lock(m); while (run) { condition.wait(lock); @@ -74,7 +76,10 @@ int main(int argc, char **argv) // Tell the host to stop listening. host.Stop(); } - else cout << "Failed to initialise host" << endl; + else + { + std::cout << "Failed to initialise host\n"; + } return 0; } diff --git a/include/examples/Cookies.hpp b/src/examples/modules/Cookies.cpp similarity index 100% rename from include/examples/Cookies.hpp rename to src/examples/modules/Cookies.cpp diff --git a/include/examples/Dependencies.hpp b/src/examples/modules/Dependencies.cpp similarity index 100% rename from include/examples/Dependencies.hpp rename to src/examples/modules/Dependencies.cpp diff --git a/include/examples/Entities.hpp b/src/examples/modules/Entities.cpp similarity index 100% rename from include/examples/Entities.hpp rename to src/examples/modules/Entities.cpp diff --git a/include/examples/Files.hpp b/src/examples/modules/Files.cpp similarity index 100% rename from include/examples/Files.hpp rename to src/examples/modules/Files.cpp diff --git a/include/examples/Hashing.hpp b/src/examples/modules/Hashing.cpp similarity index 100% rename from include/examples/Hashing.hpp rename to src/examples/modules/Hashing.cpp diff --git a/include/examples/Headers.hpp b/src/examples/modules/Headers.cpp similarity index 100% rename from include/examples/Headers.hpp rename to src/examples/modules/Headers.cpp diff --git a/include/examples/Pipeline.hpp b/src/examples/modules/Pipeline.cpp similarity index 100% rename from include/examples/Pipeline.hpp rename to src/examples/modules/Pipeline.cpp diff --git a/include/examples/Query.hpp b/src/examples/modules/Query.cpp similarity index 100% rename from include/examples/Query.hpp rename to src/examples/modules/Query.cpp diff --git a/include/examples/RouteCaptures.hpp b/src/examples/modules/RouteCaptures.cpp similarity index 100% rename from include/examples/RouteCaptures.hpp rename to src/examples/modules/RouteCaptures.cpp diff --git a/include/examples/Simple.hpp b/src/examples/modules/Simple.cpp similarity index 100% rename from include/examples/Simple.hpp rename to src/examples/modules/Simple.cpp diff --git a/src/examples/premake5.lua b/src/examples/premake5.lua index 9b8cc52..6bff057 100644 --- a/src/examples/premake5.lua +++ b/src/examples/premake5.lua @@ -17,10 +17,10 @@ solution "examples" kind "ConsoleApp" targetdir "bin" links { "niven", "hiredis", "pthread", "stdc++fs" } - files { "example.cpp" } + files { "example.cpp", "modules/**.cpp" } project "ssl" kind "ConsoleApp" targetdir "bin" links { "niven", "pthread" } - files { "ssl.cpp" } + files { "ssl.cpp", "modules/Simple.cpp" } diff --git a/src/examples/ssl.cpp b/src/examples/ssl.cpp index 3feab29..9bf9be1 100644 --- a/src/examples/ssl.cpp +++ b/src/examples/ssl.cpp @@ -6,12 +6,7 @@ // #include #include -#include "examples/Simple.hpp" - - -using namespace std; -using namespace emg; -using namespace niven; +// #include "examples/Simple.hpp" auto KEY = R"ssl( @@ -55,20 +50,20 @@ auto CERTIFICATE = R"ssl( bool run = true; -condition_variable condition; +std::condition_variable condition; int main(int argc, char **argv) { // Enable logging to stdout - Log::Initialise({ make_unique() }); - Log::Verbosity("info"); + emg::Log::Initialise({ std::make_unique() }); + emg::Log::Verbosity("info"); // Catch the interrupt/quit signals and handle appropriately signal(SIGINT, [](int) { run = false; condition.notify_one(); }); signal(SIGQUIT, [](int) { run = false; condition.notify_one(); }); - NivenHost host; + niven::NivenHost host; // Listen on port 8090 and enable SSL using an embedded key and certificate. host.Listen(8090).EnableSSL(KEY, CERTIFICATE); @@ -82,15 +77,22 @@ int main(int argc, char **argv) // variable to wait for an interrupt or quit signal from the user. if (host.Run()) { - cout << "Listening on port 8090" << endl; + std::cout << "Listening on port 8090\n"; + + std::mutex m; + std::unique_lock lock(m); - mutex m; - unique_lock lock(m); - while (run) condition.wait(lock); + while (run) + { + condition.wait(lock); + } host.Stop(); } - else cout << "Failed to initialise host" << endl; + else + { + std::cout << "Failed to initialise host\n"; + } return 0; } diff --git a/src/niven/Cookie.cpp b/src/niven/Cookie.cpp index 841d6a0..a5437c1 100644 --- a/src/niven/Cookie.cpp +++ b/src/niven/Cookie.cpp @@ -9,7 +9,7 @@ using namespace emergent; namespace niven { // Build the cookie string. - string Cookie::Build() + string Cookie::Build() const { auto result = String::format("%s=%s; Path=%s", this->name, this->value, this->path); diff --git a/src/niven/Response.cpp b/src/niven/Response.cpp index abc9b54..e1b2793 100644 --- a/src/niven/Response.cpp +++ b/src/niven/Response.cpp @@ -63,39 +63,40 @@ namespace niven int Response::Send(MHD_Connection *connection) { - if (!this->path.empty()) + MHD_Response *response = nullptr; + + if (this->path.empty()) { - if (auto file = fopen(this->path.c_str(), "rb")) - { - auto response = MHD_create_response_from_callback( - fs::file_size(this->path), - 32 * 1024, - [](void *file, uint64_t pos, char *buffer, size_t max) { - fseek((FILE *)file, pos, SEEK_SET); - return (ssize_t)fread(buffer, 1, max, (FILE *)file); - }, - file, - [](void *file) { fclose((FILE *)file); } - ); - - MHD_add_response_header(response, "Server", "niven/0.1"); - MHD_add_response_header(response, "Keep-Alive", "timeout=60"); - - int result = MHD_queue_response(connection, (int)this->status, response); - - MHD_destroy_response(response); - - return result; - } - - this->status = Http::NotFound; + // auto response = MHD_create_response_from_buffer(this->data.size(), (void *)this->data.data(), MHD_RESPMEM_PERSISTENT); + response = MHD_create_response_from_buffer(this->data.size(), (void *)this->data.data(), MHD_RESPMEM_MUST_COPY); + } + else if (auto file = fopen(this->path.c_str(), "rb")) + { + response = MHD_create_response_from_callback( + fs::file_size(this->path), + 32 * 1024, + [](void *file, uint64_t pos, char *buffer, size_t max) { + fseek((FILE *)file, pos, SEEK_SET); + return (ssize_t)fread(buffer, 1, max, (FILE *)file); + }, + file, + [](void *file) { fclose((FILE *)file); } + ); + } + else + { + response = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_MUST_COPY); + this->status = Http::NotFound; } - // auto response = MHD_create_response_from_buffer(this->data.size(), (void *)this->data.data(), MHD_RESPMEM_PERSISTENT); - auto response = MHD_create_response_from_buffer(this->data.size(), (void *)this->data.data(), MHD_RESPMEM_MUST_COPY); - - for (auto &h : this->headers) MHD_add_response_header(response, h.first.c_str(), h.second.c_str()); - for (auto &c : this->cookies) MHD_add_response_header(response, "Set-Cookie", c.Build().c_str()); + for (const auto &[name, value] : this->headers) + { + MHD_add_response_header(response, name.c_str(), value.c_str()); + } + for (const auto &c : this->cookies) + { + MHD_add_response_header(response, "Set-Cookie", c.Build().c_str()); + } MHD_add_response_header(response, "Server", "niven/0.1"); MHD_add_response_header(response, "Keep-Alive", "timeout=60");