aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlns <matzeton@googlemail.com>2021-10-21 14:52:26 +0200
committerlns <matzeton@googlemail.com>2021-10-21 14:59:00 +0200
commit9266070e51422a71566ee5c04db42feec996c485 (patch)
tree4ff57de8bfce87bde001c80c7ab9fae3080aa248
parent384724a00be9dbb8f40d295f99b9c6bcfb48b387 (diff)
Improved URI handling and redirection/routing.
* parse and process URI query strings * remove garbage slashes from URI path / sanitize * more template examples Signed-off-by: lns <matzeton@googlemail.com>
-rw-r--r--blog/my-very-first-blog-entry.md6
-rw-r--r--pages/index.md1
-rw-r--r--src/Content.hpp4
-rw-r--r--src/ContentManager.cpp44
-rw-r--r--src/ContentManager.hpp1
-rw-r--r--src/EventManager.cpp9
-rw-r--r--src/RequestResponse.cpp39
-rw-r--r--src/RequestResponse.hpp7
-rw-r--r--src/content/blog/Blog.cpp9
-rw-r--r--src/content/blog/Blog.hpp4
-rw-r--r--src/content/markdown/Markdown.cpp35
-rw-r--r--src/content/markdown/Markdown.hpp4
-rw-r--r--src/content/static/Static.cpp4
-rw-r--r--src/content/static/Static.hpp4
-rw-r--r--src/main.cpp22
-rw-r--r--wwwroot/blog/index.html27
-rw-r--r--wwwroot/index.html27
-rw-r--r--wwwroot/index.tmpl1
18 files changed, 177 insertions, 71 deletions
diff --git a/blog/my-very-first-blog-entry.md b/blog/my-very-first-blog-entry.md
index 292b1e1..017cbfc 100644
--- a/blog/my-very-first-blog-entry.md
+++ b/blog/my-very-first-blog-entry.md
@@ -1,2 +1,8 @@
Text
=======
+
+`test`
+
+```
+some code...
+```
diff --git a/pages/index.md b/pages/index.md
new file mode 100644
index 0000000..fbb8dc4
--- /dev/null
+++ b/pages/index.md
@@ -0,0 +1 @@
+*Just HTML*
diff --git a/src/Content.hpp b/src/Content.hpp
index 7539e9a..eac3657 100644
--- a/src/Content.hpp
+++ b/src/Content.hpp
@@ -19,9 +19,9 @@ public:
virtual bool Render(RequestResponse & rr, RenderData & rd, std::string & out) = 0;
- virtual std::string const & GetUriBasePath() const = 0;
+ virtual std::string & GetUriBasePath() = 0;
virtual std::string const & GetMainTemplate() const = 0;
- virtual Redirections const & GetRedirections() const = 0;
+ virtual Redirections & GetRedirections() = 0;
};
#endif
diff --git a/src/ContentManager.cpp b/src/ContentManager.cpp
index a110e05..da1ab65 100644
--- a/src/ContentManager.cpp
+++ b/src/ContentManager.cpp
@@ -7,12 +7,16 @@ void ContentManager::SetTemplateSystem(std::shared_ptr<TemplateManager> const &
bool ContentManager::RegisterModule(std::shared_ptr<Content> ctnt)
{
- std::string const & basePath = ctnt->GetUriBasePath();
+ std::string & basePath = ctnt->GetUriBasePath();
+ ContentManager::RemoveGarbageSlashes(basePath);
if (basePath.empty() == true)
{
return false;
}
+#if 0
+ std::cout << "Base URI: " << basePath << std::endl;
+#endif
m_ContentModules[basePath] = ctnt;
return true;
@@ -29,11 +33,32 @@ bool ContentManager::InitAll(void)
ret = false;
}
- Redirections const & rs = content.second->GetRedirections();
+ Redirections & rs = content.second->GetRedirections();
for (auto & redirect : rs)
{
+ ContentManager::RemoveGarbageSlashes(redirect);
+ if (redirect == content.second->GetUriBasePath())
+ {
+ continue;
+ }
+ if (m_ContentModulesRoutes.find(redirect) != m_ContentModulesRoutes.end())
+ {
+ std::cerr << "Redirect URI already exists: " << redirect << std::endl;
+ }
+ else
+ {
+#if 0
+ std::cout << "Redirect URI: " << redirect << std::endl;
+#endif
+ }
m_ContentModulesRoutes[redirect] = content.second;
}
+
+ std::string & basePath = content.second->GetUriBasePath();
+ if (basePath.back() == '/')
+ {
+ basePath.pop_back();
+ }
}
return ret;
@@ -107,3 +132,18 @@ ContentModules const & ContentManager::GetAllModulesRoutes() const
{
return m_ContentModulesRoutes;
}
+
+void ContentManager::RemoveGarbageSlashes(std::string & uri_basepath)
+{
+ size_t start_pos = 0;
+ static const std::string from = "//";
+ static const std::string to = "/";
+
+ if (from.empty())
+ return;
+ while ((start_pos = uri_basepath.find(from, start_pos)) != std::string::npos)
+ {
+ uri_basepath.replace(start_pos, from.length(), to);
+ start_pos += to.length();
+ }
+}
diff --git a/src/ContentManager.hpp b/src/ContentManager.hpp
index 674a5d0..1e45e53 100644
--- a/src/ContentManager.hpp
+++ b/src/ContentManager.hpp
@@ -28,6 +28,7 @@ public:
bool Render(char const * basePath, RequestResponse & rr, std::string & out);
ContentModules const & GetAllModules() const;
ContentModules const & GetAllModulesRoutes() const;
+ static void RemoveGarbageSlashes(std::string & uri_basepath);
private:
std::shared_ptr<TemplateManager> m_TemplateManager;
diff --git a/src/EventManager.cpp b/src/EventManager.cpp
index d45dcee..2f2da36 100644
--- a/src/EventManager.cpp
+++ b/src/EventManager.cpp
@@ -63,6 +63,9 @@ extern "C"
GenerateInternalErrorPage(req, "EvContentManagerInterceptor: path == nullptr");
return;
}
+#if 1
+ std::cout << "URI Path: " << path << std::endl;
+#endif
std::shared_ptr<ContentManager> const cmgr = *(std::shared_ptr<ContentManager> const *)ev_c_callback;
RequestResponse rr(path, req);
@@ -177,21 +180,21 @@ bool EventManager::Init(std::string host, uint16_t port)
{
if (evhttp_set_cb(m_EvHttp, cm.first.c_str(), EvContentManagerInterceptor, &m_ContentManager) != 0)
{
- return false;
+ fprintf(stderr, "Failed to add module callback: %s\n", cm.first.c_str());
}
}
for (auto & cm : m_ContentManager->GetAllModulesRoutes())
{
if (evhttp_set_cb(m_EvHttp, cm.first.c_str(), EvContentManagerInterceptor, &m_ContentManager) != 0)
{
- return false;
+ fprintf(stderr, "Failed to add route callback: %s\n", cm.first.c_str());
}
}
evhttp_set_gencb(m_EvHttp, EvGenericInterceptor, &m_DefaultCallback);
if (evhttp_bind_socket(m_EvHttp, host.c_str(), port) != 0)
{
- fprintf(stderr, "couldn't bind to %s:%d. Exiting.\n", host.c_str(), port);
+ fprintf(stderr, "Couldn't bind to %s:%d. Exiting.\n", host.c_str(), port);
return false;
}
diff --git a/src/RequestResponse.cpp b/src/RequestResponse.cpp
index 803b432..c3247e9 100644
--- a/src/RequestResponse.cpp
+++ b/src/RequestResponse.cpp
@@ -1,12 +1,13 @@
#include "RequestResponse.hpp"
RequestResponse::RequestResponse(char const * const uri_path, struct evhttp_request * const req)
- : m_UriPath(uri_path), m_Request(req)
+ : m_UriPath(uri_path), m_Request(req), m_InputHeader(nullptr), m_OutputHeader(nullptr)
{
}
RequestResponse::~RequestResponse()
{
+ evhttp_clear_headers(&m_Query);
}
void RequestResponse::UseInputHeader()
@@ -19,13 +20,23 @@ void RequestResponse::UseOutputHeader()
m_OutputHeader = evhttp_request_get_output_headers(m_Request);
}
-bool RequestResponse::AddOutputHeaderByRef(std::string const & key, std::string const & value)
+bool RequestResponse::UseUri()
{
- if (m_OutputHeader == nullptr)
+ struct evhttp_uri const * const uri = evhttp_request_get_evhttp_uri(m_Request);
+ if (uri == nullptr)
+ {
+ return false;
+ }
+ char const * const query = evhttp_uri_get_query(uri);
+ if (query == nullptr)
{
return false;
}
+ return evhttp_parse_query_str(query, &m_Query) == 0;
+}
+bool RequestResponse::AddOutputHeaderByRef(std::string const & key, std::string const & value)
+{
return evhttp_add_header(m_OutputHeader, key.c_str(), value.c_str()) == 0;
}
@@ -36,11 +47,6 @@ bool RequestResponse::AddOutputHeader(std::string const key, std::string const v
bool RequestResponse::RemoveOutputHeaderByRef(std::string const & key)
{
- if (m_OutputHeader == nullptr)
- {
- return false;
- }
-
return evhttp_remove_header(m_OutputHeader, key.c_str()) == 0;
}
@@ -51,11 +57,6 @@ bool RequestResponse::RemoveOutputHeader(std::string const 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)
@@ -71,3 +72,15 @@ bool RequestResponse::GetInputHeader(std::string const key, std::string value)
{
return GetInputHeaderByRef(key, value);
}
+
+bool RequestResponse::QueryValueEquals(std::string key, std::string value)
+{
+ char const * const v = evhttp_find_header(&m_Query, key.c_str());
+
+ if (v == nullptr)
+ {
+ return false;
+ }
+
+ return value == std::string(v);
+}
diff --git a/src/RequestResponse.hpp b/src/RequestResponse.hpp
index da2a27d..3dccd54 100644
--- a/src/RequestResponse.hpp
+++ b/src/RequestResponse.hpp
@@ -2,13 +2,14 @@
#define REQUEST_RESPONSE_H 1
#include <event2/http.h>
+#include <event2/keyvalq_struct.h>
#include <string>
class RequestResponse
{
public:
- RequestResponse(char const * const uri_path, struct evhttp_request * const req);
+ explicit RequestResponse(char const * const uri_path, struct evhttp_request * const req);
~RequestResponse();
char const * GetUriPath() const
@@ -18,6 +19,7 @@ public:
void UseInputHeader();
void UseOutputHeader();
+ bool UseUri();
bool AddOutputHeaderByRef(std::string const & key, std::string const & value);
bool AddOutputHeader(std::string const key, std::string const value);
@@ -28,11 +30,14 @@ public:
bool GetInputHeaderByRef(std::string const & key, std::string & value);
bool GetInputHeader(std::string const key, std::string value);
+ bool QueryValueEquals(std::string key, std::string value);
+
private:
char const * const m_UriPath;
struct evhttp_request * const m_Request;
struct evkeyvalq * m_InputHeader;
struct evkeyvalq * m_OutputHeader;
+ struct evkeyvalq m_Query = {};
};
#endif
diff --git a/src/content/blog/Blog.cpp b/src/content/blog/Blog.cpp
index ba8638e..47a3292 100644
--- a/src/content/blog/Blog.cpp
+++ b/src/content/blog/Blog.cpp
@@ -17,7 +17,8 @@ bool Blog::Init()
{
bool retval = true;
- std::cout << "Blog entries path: " << m_BlogPath << std::endl;
+ std::cout << "Blog entries filesystem path: " << m_BlogPath << std::endl;
+ std::cout << "Blog entries URI base path: " << m_UriBasePath << std::endl;
std::vector<std::string> extensions = {"json"};
Filesystem fs;
@@ -39,7 +40,7 @@ bool Blog::Init()
}
m_BlogEntriesSortedByDate.push_back(be);
- m_Redirections.push_back(std::filesystem::path(jfile.first).stem());
+ m_Redirections.push_back(m_UriBasePath + "/" + std::string(std::filesystem::path(jfile.first).stem()));
}
std::sort(m_BlogEntriesSortedByDate.begin(),
m_BlogEntriesSortedByDate.end(),
@@ -81,7 +82,7 @@ bool Blog::Render(RequestResponse & rr, RenderData & rd, std::string & out)
return true;
}
-std::string const & Blog::GetUriBasePath() const
+std::string & Blog::GetUriBasePath()
{
return m_UriBasePath;
}
@@ -91,7 +92,7 @@ std::string const & Blog::GetMainTemplate() const
return m_MainTemplatePath;
}
-Redirections const & Blog::GetRedirections() const
+Redirections & Blog::GetRedirections()
{
return m_Redirections;
}
diff --git a/src/content/blog/Blog.hpp b/src/content/blog/Blog.hpp
index d99185a..d58cd72 100644
--- a/src/content/blog/Blog.hpp
+++ b/src/content/blog/Blog.hpp
@@ -38,9 +38,9 @@ public:
void Shutdown();
bool Render(RequestResponse & rr, RenderData & rd, std::string & out);
- std::string const & GetUriBasePath() const;
+ std::string & GetUriBasePath();
std::string const & GetMainTemplate() const;
- Redirections const & GetRedirections() const;
+ Redirections & GetRedirections();
static bool ValidateAndSetMetdadata(BlogMetadata const & blogMetadata, BlogEntry & blogEntry);
bool ValidateEntries() const;
diff --git a/src/content/markdown/Markdown.cpp b/src/content/markdown/Markdown.cpp
index a85f333..903fcec 100644
--- a/src/content/markdown/Markdown.cpp
+++ b/src/content/markdown/Markdown.cpp
@@ -8,6 +8,11 @@ Markdown::Markdown(std::string uriBasePath, std::string markdownFilesPath, std::
m_MainTemplatePath(mainTemplatePath),
m_MarkdownFilesPath(markdownFilesPath)
{
+ if (m_MainTemplatePath.empty() == false)
+ {
+ m_Redirections.push_back(uriBasePath + "/");
+ m_Redirections.push_back(uriBasePath + "/index.html");
+ }
}
extern "C" void markdown_to_html_conversion(const MD_CHAR * const text, MD_SIZE size, void * const userdata)
@@ -20,6 +25,10 @@ extern "C" void markdown_to_html_conversion(const MD_CHAR * const text, MD_SIZE
bool Markdown::Init()
{
std::cout << "Markdown files path: " << m_MarkdownFilesPath << std::endl;
+ if (m_UriBasePath.empty() == false)
+ {
+ std::cout << "Markdown files URI base path: " << m_UriBasePath << std::endl;
+ }
std::vector<std::string> extensions = {"md"};
@@ -68,15 +77,35 @@ bool Markdown::Render(RequestResponse & rr, RenderData & rd, std::string & out)
(void)rd;
(void)out;
+ std::string md_file;
+
if (m_MainTemplatePath.empty() == true)
{
return false;
}
- return false; /* TODO: Make markdown module usable as standalone module?! */
+ if (rr.GetUriPath() == m_UriBasePath || rr.GetUriPath() == m_UriBasePath + "/" ||
+ rr.GetUriPath() == m_UriBasePath + "/index.html")
+ {
+ rr.UseUri();
+ if (rr.QueryValueEquals("get", "bla") == true)
+ {
+ rd["content"] = "bla";
+ }
+ else
+ {
+ rd["content"] = "blubb";
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
}
-std::string const & Markdown::GetUriBasePath() const
+std::string & Markdown::GetUriBasePath()
{
return m_UriBasePath;
}
@@ -86,7 +115,7 @@ std::string const & Markdown::GetMainTemplate() const
return m_MainTemplatePath;
}
-Redirections const & Markdown::GetRedirections() const
+Redirections & Markdown::GetRedirections()
{
return m_Redirections;
}
diff --git a/src/content/markdown/Markdown.hpp b/src/content/markdown/Markdown.hpp
index 9c4d3c4..fa14b3a 100644
--- a/src/content/markdown/Markdown.hpp
+++ b/src/content/markdown/Markdown.hpp
@@ -15,9 +15,9 @@ public:
void Shutdown();
bool Render(RequestResponse & rr, RenderData & rd, std::string & out);
- std::string const & GetUriBasePath() const;
+ std::string & GetUriBasePath();
std::string const & GetMainTemplate() const;
- Redirections const & GetRedirections() const;
+ Redirections & GetRedirections();
bool HasMarkdownFile(std::string filePath) const;
bool HasMarkdownURI(std::string uriPath) const;
diff --git a/src/content/static/Static.cpp b/src/content/static/Static.cpp
index 132f0a0..93f9905 100644
--- a/src/content/static/Static.cpp
+++ b/src/content/static/Static.cpp
@@ -44,7 +44,7 @@ bool Static::Render(RequestResponse & rr, RenderData & rd, std::string & out)
return true;
}
-std::string const & Static::GetUriBasePath() const
+std::string & Static::GetUriBasePath()
{
return m_UriBasePath;
}
@@ -54,7 +54,7 @@ std::string const & Static::GetMainTemplate() const
return m_MainTemplatePath;
}
-Redirections const & Static::GetRedirections() const
+Redirections & Static::GetRedirections()
{
return m_Redirections;
}
diff --git a/src/content/static/Static.hpp b/src/content/static/Static.hpp
index b9de983..8d702ec 100644
--- a/src/content/static/Static.hpp
+++ b/src/content/static/Static.hpp
@@ -13,9 +13,9 @@ public:
void Shutdown();
bool Render(RequestResponse & rr, RenderData & rd, std::string & out);
- std::string const & GetUriBasePath() const;
+ std::string & GetUriBasePath();
std::string const & GetMainTemplate() const;
- Redirections const & GetRedirections() const;
+ Redirections & GetRedirections();
private:
std::string m_UriBasePath;
diff --git a/src/main.cpp b/src/main.cpp
index 4969d70..dcd24a2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,6 +13,7 @@
int main(int argc, char ** argv)
{
+ std::string wwwroot = "./wwwroot";
char const * host = "127.0.0.1";
uint16_t port = 9000;
@@ -35,8 +36,8 @@ int main(int argc, char ** argv)
}
std::shared_ptr<TemplateManager> tmgr = std::make_shared<TemplateManager>();
- std::shared_ptr<ContentManager> ctmgr = std::make_shared<ContentManager>();
- ctmgr->SetTemplateSystem(tmgr);
+ std::shared_ptr<ContentManager> cmgr = std::make_shared<ContentManager>();
+ cmgr->SetTemplateSystem(tmgr);
{
std::shared_ptr<Filesystem> static_fs = std::make_shared<Filesystem>();
@@ -47,9 +48,10 @@ int main(int argc, char ** argv)
return 1;
}
}
- static_fs->Scan("./wwwroot", {"html", "tmpl"}, true);
+ std::cout << "Static fs: " << wwwroot << std::endl;
+ static_fs->Scan(wwwroot, {"html", "tmpl"}, true);
- ctmgr->RegisterModule(std::make_shared<Static>("/static", static_fs));
+ cmgr->RegisterModule(std::make_shared<Static>("/static", static_fs));
}
{
@@ -61,21 +63,23 @@ int main(int argc, char ** argv)
return 1;
}
}
- dynamic_fs.Scan("./wwwroot", {"html", "tmpl"}, false);
+ std::cout << "Dynamic fs: " << wwwroot << std::endl;
+ dynamic_fs.Scan(wwwroot, {"html", "tmpl"}, false);
tmgr->ParseTemplates(dynamic_fs);
}
- ctmgr->RegisterModule(std::make_shared<Blog>("/blog", "index.html", "./blog"));
+ cmgr->RegisterModule(std::make_shared<Markdown>("/", "./pages", "index.html"));
+ cmgr->RegisterModule(std::make_shared<Blog>("/blog", "blog/index.html", "./blog"));
- if (ctmgr->InitAll() == false)
+ if (cmgr->InitAll() == false)
{
std::cout << "InitAll() failed." << std::endl;
return 1;
}
- EventManager evmgr(ctmgr);
+ EventManager evmgr(cmgr);
evmgr.Init(host, port);
- // ctmgr.ShutdownAll();
+ // cmgr.ShutdownAll();
}
diff --git a/wwwroot/blog/index.html b/wwwroot/blog/index.html
new file mode 100644
index 0000000..554a952
--- /dev/null
+++ b/wwwroot/blog/index.html
@@ -0,0 +1,27 @@
+<html><body>
+<p>
+<b>blabla</b>
+Test fn....: <b>{{ test_fn }}</b><br>
+Test RetFN.: <b>{{ test_return_true }}</b><br><br><br>
+{% if exists("blog_listing") and length(blog_listing) > 0 %}
+<table>
+## for entry in blog_listing
+ <tr>
+ <td>{{ loop.index1 }}</td>
+ <td>{{ entry.content_filename }}</td>
+ <td>{{ entry.title }}</td>
+ <td>{{ entry.tags }}</td>
+ <td>{{ entry.author }}</td>
+ <td>{{ entry.createDate }}</td>
+ <td>{{ entry.publishDate }}</td>
+ <td>{{ entry.published }}</td>
+ <td>
+ {{ indent(entry.content, 12, false, false) }}
+ </td>
+ <td>{% if loop.is_last == false %}more{% else %}eof{% endif %}<br>
+ </tr>
+## endfor
+</table>
+{% endif %}
+</p>
+</body></html>
diff --git a/wwwroot/index.html b/wwwroot/index.html
index 554a952..9b05eee 100644
--- a/wwwroot/index.html
+++ b/wwwroot/index.html
@@ -1,27 +1,4 @@
<html><body>
-<p>
-<b>blabla</b>
-Test fn....: <b>{{ test_fn }}</b><br>
-Test RetFN.: <b>{{ test_return_true }}</b><br><br><br>
-{% if exists("blog_listing") and length(blog_listing) > 0 %}
-<table>
-## for entry in blog_listing
- <tr>
- <td>{{ loop.index1 }}</td>
- <td>{{ entry.content_filename }}</td>
- <td>{{ entry.title }}</td>
- <td>{{ entry.tags }}</td>
- <td>{{ entry.author }}</td>
- <td>{{ entry.createDate }}</td>
- <td>{{ entry.publishDate }}</td>
- <td>{{ entry.published }}</td>
- <td>
- {{ indent(entry.content, 12, false, false) }}
- </td>
- <td>{% if loop.is_last == false %}more{% else %}eof{% endif %}<br>
- </tr>
-## endfor
-</table>
-{% endif %}
-</p>
+ <b>INDEX TMPL</b>
+ {{ content }}
</body></html>
diff --git a/wwwroot/index.tmpl b/wwwroot/index.tmpl
deleted file mode 100644
index b42f18c..0000000
--- a/wwwroot/index.tmpl
+++ /dev/null
@@ -1 +0,0 @@
-<html><body><b>INDEX TMPL</b></body></html>