aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2021-10-04 16:56:02 +0200
committerToni Uhlig <matzeton@googlemail.com>2021-10-04 16:56:02 +0200
commitf0f4b8a4d139a855ad15f9d79190edf6320eba51 (patch)
tree4ba361738f08bf44769e3454832d765ba8d7f2c1
parent5ff3d7a51be30a0052b12f9330fdf54f3c104739 (diff)
Static file cache content module.
* remove EVHTTP headers * magic/mime type support for virtual Filesystem Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/ContentManager.cpp2
-rw-r--r--src/ContentManager.hpp3
-rw-r--r--src/EventManager.cpp18
-rw-r--r--src/EventManager.hpp1
-rw-r--r--src/Filesystem.cpp44
-rw-r--r--src/Filesystem.hpp17
-rw-r--r--src/RequestResponse.cpp40
-rw-r--r--src/RequestResponse.hpp19
-rw-r--r--src/TemplateManager.cpp2
-rw-r--r--src/TemplateManager.hpp2
-rw-r--r--src/content/static/Static.cpp31
-rw-r--r--src/content/static/Static.hpp7
-rw-r--r--src/main.cpp9
14 files changed, 138 insertions, 59 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9972193..ecc3b2d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,4 +19,4 @@ add_executable(cpp-web ${SOURCES})
if(CMAKE_BUILD_TYPE MATCHES Release)
set_target_properties(cpp-web PROPERTIES LINK_FLAGS "-no-pie -flto -Wl,--gc-sections -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,--build-id=none")
endif()
-target_link_libraries(cpp-web stdc++fs pthread event)
+target_link_libraries(cpp-web stdc++fs pthread event magic)
diff --git a/src/ContentManager.cpp b/src/ContentManager.cpp
index ace325e..8bff717 100644
--- a/src/ContentManager.cpp
+++ b/src/ContentManager.cpp
@@ -1,6 +1,6 @@
#include "ContentManager.hpp"
-void ContentManager::SetTemplateSystem(std::shared_ptr<TemplateManager> & tmgr)
+void ContentManager::SetTemplateSystem(std::shared_ptr<TemplateManager> const & tmgr)
{
m_TemplateManager = tmgr;
}
diff --git a/src/ContentManager.hpp b/src/ContentManager.hpp
index 9ae7271..674a5d0 100644
--- a/src/ContentManager.hpp
+++ b/src/ContentManager.hpp
@@ -21,8 +21,7 @@ public:
ShutdownAll();
}
- void SetStaticFilesystem(std::shared_ptr<Filesystem> & static_fs);
- void SetTemplateSystem(std::shared_ptr<TemplateManager> & tmgr);
+ void SetTemplateSystem(std::shared_ptr<TemplateManager> const & tmgr);
bool RegisterModule(std::shared_ptr<Content> ctnt);
bool InitAll(void);
void ShutdownAll(void);
diff --git a/src/EventManager.cpp b/src/EventManager.cpp
index bc4b5cb..6c735a8 100644
--- a/src/EventManager.cpp
+++ b/src/EventManager.cpp
@@ -10,8 +10,18 @@
extern "C"
{
+ struct chunk_req_state
+ {
+ struct event_base * base;
+ struct evhttp_request * req;
+ struct event * timer;
+
+ off_t out_offset;
+ };
+
static void GenerateInternalErrorPage(struct evhttp_request * const req, std::string text)
{
+ evhttp_clear_headers(evhttp_request_get_output_headers(req));
evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html");
struct evbuffer * const output = evbuffer_new();
@@ -55,7 +65,7 @@ extern "C"
}
std::shared_ptr<ContentManager> const cmgr = *(std::shared_ptr<ContentManager> const *)ev_c_callback;
- RequestResponse rr(req);
+ RequestResponse rr(path, req);
std::string out;
if (cmgr->Render(path, rr, out) == false)
@@ -66,8 +76,6 @@ extern "C"
}
else
{
- evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html");
-
struct evbuffer * const output = evbuffer_new();
if (output != nullptr)
{
@@ -213,3 +221,7 @@ void EventManager::AddCallback(std::string url, EvFunction fn, EvUserData dat)
{
m_UrlCallbacks.push_back(EvUrlCallback(url, {fn, dat}));
}
+
+void EventManager::AddChunkedCallback(std::string url, EvFunction fn, EvUserData dat, struct timeval chunk_timer)
+{
+}
diff --git a/src/EventManager.hpp b/src/EventManager.hpp
index cf09e14..5d74602 100644
--- a/src/EventManager.hpp
+++ b/src/EventManager.hpp
@@ -32,6 +32,7 @@ public:
bool Init(std::string = "127.0.0.1", uint16_t port = 9000);
void SetDefaultCallback(EvFunction fn, EvUserData dat);
void AddCallback(std::string url, EvFunction fn, EvUserData dat);
+ void AddChunkedCallback(std::string url, EvFunction fn, EvUserData dat, struct timeval chunk_timer);
private:
std::shared_ptr<ContentManager> m_ContentManager;
diff --git a/src/Filesystem.cpp b/src/Filesystem.cpp
index 09e5146..04dbb1b 100644
--- a/src/Filesystem.cpp
+++ b/src/Filesystem.cpp
@@ -10,8 +10,18 @@ static std::string make_path_relative(std::string & path, std::string & root)
return std::filesystem::relative(path, root);
}
+static bool is_directory(std::string & path)
+{
+ return std::filesystem::is_directory(path);
+}
+
bool Filesystem::AddSingleFile(std::string path, std::string root)
{
+ if (is_directory(path) == true)
+ {
+ return true;
+ }
+
std::ifstream ifs(path, std::ios::binary | std::ios::ate);
if (!ifs)
@@ -29,9 +39,9 @@ bool Filesystem::AddSingleFile(std::string path, std::string root)
return false;
}
- auto size = std::size_t(end - ifs.tellg());
+ auto size = end - ifs.tellg();
- if (size == 0)
+ if (size <= 0)
{
return false;
}
@@ -62,6 +72,7 @@ bool Filesystem::AddSingleFile(std::string path, std::string root)
std::cout << "Adding file: " << path << " (" << size << " bytes) as " << relpath << " to " << this << std::endl;
}
+ fd.mime = magic_file(m_Magic, path.c_str());
m_Files[relpath] = fd;
return true;
@@ -69,24 +80,14 @@ bool Filesystem::AddSingleFile(std::string path, std::string root)
bool Filesystem::Scan(std::string root)
{
- bool retval = true;
-
- for (const auto & entry : std::filesystem::directory_iterator(root))
- {
- if (AddSingleFile(entry.path(), root) == false)
- {
- retval = true;
- }
- }
-
- return retval;
+ return Scan(root, {}, true);
}
bool Filesystem::Scan(std::string root, std::vector<std::string> extensions, bool exclude_extensions)
{
bool retval = true;
- for (const auto & entry : std::filesystem::directory_iterator(root))
+ for (const auto & entry : std::filesystem::recursive_directory_iterator(root))
{
std::string ext = std::filesystem::path(entry).extension();
bool found_extension = false;
@@ -119,7 +120,20 @@ bool Filesystem::Scan(std::string root, std::vector<std::string> extensions, boo
return retval;
}
-const std::unordered_map<std::string, struct file_data> & Filesystem::GetFiles() const
+FilesDict & Filesystem::GetFiles()
{
return m_Files;
}
+
+void Filesystem::MagicInit()
+{
+ m_Magic = magic_open(MAGIC_MIME_TYPE);
+
+ magic_load(m_Magic, NULL);
+ magic_compile(m_Magic, NULL);
+}
+
+void Filesystem::MagicClose()
+{
+ magic_close(m_Magic);
+}
diff --git a/src/Filesystem.hpp b/src/Filesystem.hpp
index 13733c9..02150fb 100644
--- a/src/Filesystem.hpp
+++ b/src/Filesystem.hpp
@@ -1,13 +1,18 @@
#ifndef FILESYSTEM_H
#define FILESYSTEM_H 1
+#include <magic.h>
+
#include <inja/inja.hpp>
#include <string>
#include <unordered_map>
#include <vector>
+using FilesDict = std::unordered_map<std::string, struct file_data>;
+
struct file_data
{
+ std::string mime;
std::vector<unsigned char> data;
};
@@ -16,18 +21,24 @@ class Filesystem
public:
Filesystem()
{
+ MagicInit();
}
~Filesystem()
{
+ MagicClose();
}
- bool AddSingleFile(std::string path, std::string root);
bool Scan(std::string root = "./wwwroot");
bool Scan(std::string root, std::vector<std::string> extensions, bool exclude_extensions = false);
- const std::unordered_map<std::string, struct file_data> & GetFiles() const;
+ FilesDict & GetFiles();
private:
- std::unordered_map<std::string, struct file_data> m_Files;
+ bool AddSingleFile(std::string path, std::string root);
+ void MagicInit();
+ void MagicClose();
+
+ FilesDict m_Files;
+ magic_t m_Magic;
};
#endif
diff --git a/src/RequestResponse.cpp b/src/RequestResponse.cpp
index 2567253..803b432 100644
--- a/src/RequestResponse.cpp
+++ b/src/RequestResponse.cpp
@@ -1,6 +1,7 @@
#include "RequestResponse.hpp"
-RequestResponse::RequestResponse(struct evhttp_request * const req) : m_Request(req)
+RequestResponse::RequestResponse(char const * const uri_path, struct evhttp_request * const req)
+ : m_UriPath(uri_path), m_Request(req)
{
}
@@ -18,18 +19,43 @@ void RequestResponse::UseOutputHeader()
m_OutputHeader = evhttp_request_get_output_headers(m_Request);
}
-bool RequestResponse::AddOutputHeaderByRef(std::string & key, std::string & value)
+bool RequestResponse::AddOutputHeaderByRef(std::string const & key, std::string const & value)
{
- return evhttp_add_header(m_OutputHeader, key.c_str(), value.c_str());
+ if (m_OutputHeader == nullptr)
+ {
+ return false;
+ }
+
+ return evhttp_add_header(m_OutputHeader, key.c_str(), value.c_str()) == 0;
}
-bool RequestResponse::AddOutputHeader(std::string key, std::string value)
+bool RequestResponse::AddOutputHeader(std::string const key, std::string const value)
{
return AddOutputHeaderByRef(key, value);
}
-bool RequestResponse::GetInputHeaderByRef(std::string & key, std::string & value)
+bool RequestResponse::RemoveOutputHeaderByRef(std::string const & key)
+{
+ if (m_OutputHeader == nullptr)
+ {
+ return false;
+ }
+
+ return evhttp_remove_header(m_OutputHeader, key.c_str()) == 0;
+}
+
+bool RequestResponse::RemoveOutputHeader(std::string const key)
+{
+ return RemoveOutputHeaderByRef(key);
+}
+
+bool RequestResponse::GetInputHeaderByRef(std::string const & key, std::string & value)
{
+ if (m_InputHeader == nullptr)
+ {
+ return false;
+ }
+
char const * const v = evhttp_find_header(m_InputHeader, key.c_str());
if (v == nullptr)
@@ -41,7 +67,7 @@ bool RequestResponse::GetInputHeaderByRef(std::string & key, std::string & value
return true;
}
-bool RequestResponse::GetInputHeader(std::string key, std::string value)
+bool RequestResponse::GetInputHeader(std::string const key, std::string value)
{
- return GetInputHeader(key, value);
+ return GetInputHeaderByRef(key, value);
}
diff --git a/src/RequestResponse.hpp b/src/RequestResponse.hpp
index 8a7e1d3..da2a27d 100644
--- a/src/RequestResponse.hpp
+++ b/src/RequestResponse.hpp
@@ -8,19 +8,28 @@
class RequestResponse
{
public:
- RequestResponse(struct evhttp_request * const req);
+ RequestResponse(char const * const uri_path, struct evhttp_request * const req);
~RequestResponse();
+ char const * GetUriPath() const
+ {
+ return m_UriPath;
+ }
+
void UseInputHeader();
void UseOutputHeader();
- bool AddOutputHeaderByRef(std::string & key, std::string & value);
- bool AddOutputHeader(std::string key, std::string value);
+ bool AddOutputHeaderByRef(std::string const & key, std::string const & value);
+ bool AddOutputHeader(std::string const key, std::string const value);
+
+ bool RemoveOutputHeaderByRef(std::string const & key);
+ bool RemoveOutputHeader(std::string const key);
- bool GetInputHeaderByRef(std::string & key, std::string & value);
- bool GetInputHeader(std::string key, std::string value);
+ bool GetInputHeaderByRef(std::string const & key, std::string & value);
+ bool GetInputHeader(std::string const key, std::string value);
private:
+ char const * const m_UriPath;
struct evhttp_request * const m_Request;
struct evkeyvalq * m_InputHeader;
struct evkeyvalq * m_OutputHeader;
diff --git a/src/TemplateManager.cpp b/src/TemplateManager.cpp
index 06771ea..a751116 100644
--- a/src/TemplateManager.cpp
+++ b/src/TemplateManager.cpp
@@ -14,7 +14,7 @@ TemplateManager::TemplateManager()
});
}
-void TemplateManager::ParseTemplates(Filesystem const & fs)
+void TemplateManager::ParseTemplates(Filesystem & fs)
{
for (auto & tpl : fs.GetFiles())
{
diff --git a/src/TemplateManager.hpp b/src/TemplateManager.hpp
index 7b89d71..1d98c50 100644
--- a/src/TemplateManager.hpp
+++ b/src/TemplateManager.hpp
@@ -14,7 +14,7 @@ public:
{
}
- void ParseTemplates(Filesystem const & fs);
+ void ParseTemplates(Filesystem & fs);
void AddInjaCallback(std::string functionName, std::size_t numberOfArgs, inja::CallbackFunction function);
void AddVoidInjaCallback(std::string functionName, std::size_t numberOfArgs, inja::VoidCallbackFunction function);
bool TemplateExists(std::string const & templatePath);
diff --git a/src/content/static/Static.cpp b/src/content/static/Static.cpp
index 5e38b76..b9977a9 100644
--- a/src/content/static/Static.cpp
+++ b/src/content/static/Static.cpp
@@ -1,20 +1,18 @@
#include "Static.hpp"
-Static::Static(std::string uriBasePath, std::string staticFilesPath)
- : Content(), m_UriBasePath(uriBasePath), m_MainTemplatePath(""), m_StaticFilesPath(staticFilesPath)
+Static::Static(std::string uriBasePath, std::shared_ptr<Filesystem> const & fs)
+ : Content(), m_UriBasePath(uriBasePath), m_MainTemplatePath(""), m_StaticFiles(fs)
{
+ for (auto const & file : fs->GetFiles())
+ {
+ m_Redirections.push_back(uriBasePath + "/" + file.first);
+ m_UriToFsMapping[uriBasePath + "/" + file.first] = file.first;
+ }
}
bool Static::Init()
{
- std::cout << "Static files path: " << m_StaticFilesPath << std::endl;
-
- std::vector<std::string> extensions = {"json"};
-
- if (m_StaticFiles.Scan(m_StaticFilesPath, extensions, false) == false)
- {
- return false;
- }
+ std::cout << "Static files: " << m_StaticFiles->GetFiles().size() << std::endl;
return true;
}
@@ -26,11 +24,18 @@ void Static::Shutdown()
bool Static::Render(RequestResponse & rr, RenderData & rd, std::string & out)
{
- (void)rr;
(void)rd;
- (void)out;
- rd["blah"] = "Yooooh!";
+ rr.UseOutputHeader();
+ auto & files = m_StaticFiles->GetFiles();
+ auto const & path = std::string(rr.GetUriPath());
+
+ if (rr.AddOutputHeader("Content-Type", files[m_UriToFsMapping[path]].mime) == false)
+ {
+ return false;
+ }
+
+ out = std::string(files[m_UriToFsMapping[path]].data.begin(), files[m_UriToFsMapping[path]].data.end());
return true;
}
diff --git a/src/content/static/Static.hpp b/src/content/static/Static.hpp
index 85ffd8c..8dcf410 100644
--- a/src/content/static/Static.hpp
+++ b/src/content/static/Static.hpp
@@ -3,12 +3,11 @@
#include "../../Content.hpp"
#include "../../Filesystem.hpp"
-#include "../markdown/Markdown.hpp"
class Static : public Content
{
public:
- explicit Static(std::string uriBasePath, std::string staticFilesPath);
+ explicit Static(std::string uriBasePath, std::shared_ptr<Filesystem> const & fs);
bool Init();
void Shutdown();
@@ -21,9 +20,9 @@ public:
private:
std::string m_UriBasePath;
std::string m_MainTemplatePath;
- std::string m_StaticFilesPath;
Redirections m_Redirections;
- Filesystem m_StaticFiles;
+ std::shared_ptr<Filesystem> const m_StaticFiles;
+ std::unordered_map<std::string, std::string> m_UriToFsMapping;
};
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 6d41907..50f0ec5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4,6 +4,7 @@
#include "TemplateManager.hpp"
#include "content/blog/Blog.hpp"
+#include "content/static/Static.hpp"
#include <event2/buffer.h>
@@ -93,15 +94,17 @@ int main(int argc, char ** argv)
ctmgr->SetTemplateSystem(tmgr);
{
- Filesystem static_fs;
+ std::shared_ptr<Filesystem> static_fs = std::make_shared<Filesystem>();
if (argc > 3)
{
- if (static_fs.Scan(argv[3]) != true)
+ if (static_fs->Scan(argv[3]) != true)
{
return 1;
}
}
- static_fs.Scan("./wwwroot", {"html", "tmpl"}, true);
+ static_fs->Scan("./wwwroot", {"html", "tmpl"}, true);
+
+ ctmgr->RegisterModule(std::make_shared<Static>("/static", static_fs));
}
{