cache refinement

main
Brett 2023-08-20 23:48:11 -04:00
parent 2f4b2a8c98
commit 4baf70ad0c
6 changed files with 100 additions and 151 deletions

View File

@ -8,8 +8,8 @@
#include <unordered_map>
#include <blt/std/hashmap.h>
#define CROW_STATIC_DIRECTORY "/mnt/games/Projects/cpp/crowsite/crow_test/static/"
#define SITE_FILES_PATH "/mnt/games/Projects/cpp/crowsite/crow_test"
#define CROW_STATIC_DIRECTORY "/home/brett/projects/cpp/crowsite/crow_test/static/"
#define SITE_FILES_PATH "/home/brett/projects/cpp/crowsite/crow_test"
#define CROW_STATIC_ENDPOINT "/static/<path>"
#define MILES_SITE

View File

@ -10,6 +10,11 @@
namespace cs {
class LexerSyntaxError : public std::runtime_error {
public:
LexerSyntaxError(): std::runtime_error("Invalid template syntax. EOF occurred before template was fully processed!"){}
};
constexpr uint64_t toMB = 1024 * 1024;
struct CacheSettings {

View File

@ -12,52 +12,6 @@
namespace cs {
struct StringLexer
{
private:
std::string str;
size_t index = 0;
public:
explicit StringLexer(std::string str): str(std::move(str))
{}
inline bool hasNext()
{
if (index >= str.size())
return false;
return true;
}
inline bool hasTemplatePrefix(char c)
{
if (index + 2 >= str.size())
return false;
return str[index] == '{' && str[index + 1] == '{' && str[index + 2] == c;
}
inline bool hasTemplateSuffix()
{
if (index + 1 >= str.size())
return false;
return str[index] == '}' && str[index + 1] == '}';
}
inline void consumeTemplatePrefix()
{
index += 3;
}
inline void consumeTemplateSuffix()
{
index += 2;
}
inline char consume()
{
return str[index++];
}
};
class StaticContext {
private:
HASHMAP<std::string, std::string> replacements;
@ -82,16 +36,6 @@ namespace cs {
explicit HTMLPage(std::string siteData);
public:
static std::unique_ptr<HTMLPage> load(const std::string& path);
/**
* Attempts to resolve linked resources like CSS and JS in order to speedup page loading.
*/
void resolveResources();
/**
* Uses the static context provided to resolve known variables before user requests
* @param context context to use
* @return string containing resolved static templates
*/
std::string render(StaticContext& context);
inline std::string& getRawSite() {
return m_SiteData;

View File

@ -10,6 +10,72 @@
namespace cs
{
struct StringLexer
{
private:
std::string str;
size_t index = 0;
public:
explicit StringLexer(std::string str): str(std::move(str))
{}
inline bool hasNext()
{
if (index >= str.size())
return false;
return true;
}
inline bool hasTemplatePrefix(char c)
{
if (index + 2 >= str.size())
return false;
return str[index] == '{' && str[index + 1] == '{' && str[index + 2] == c;
}
inline bool hasTemplateSuffix()
{
if (index + 1 >= str.size())
return false;
return str[index] == '}' && str[index + 1] == '}';
}
inline void consumeTemplatePrefix()
{
// because any custom mustache syntax will have to have a prefix like '$' or '@'
// it is fine that we make the assumption of 3 characters consumed.
index += 3;
}
inline void consumeTemplateSuffix()
{
index += 2;
}
/**
* This function assumes hasTemplatePrefix(char) has returned true and will consume both the prefix and suffix
* @return the token found between the prefix and suffix
* @throws LexerSyntaxError if the parser is unable to process a full token
*/
inline std::string consumeToken(){
consumeTemplatePrefix();
std::string token;
while (!hasTemplateSuffix()) {
if (!hasNext()) {
throw LexerSyntaxError();
}
token += consume();
}
consumeTemplateSuffix();
return token;
}
inline char consume()
{
return str[index++];
}
};
double toSeconds(uint64_t v)
{
@ -92,7 +158,7 @@ namespace cs
auto fullPath = cs::fs::createWebFilePath(path);
auto page = HTMLPage::load(fullPath);
resolveLinks(path, *page);
auto renderedPage = page->render(m_Context);
const auto& renderedPage = page->getRawSite();
m_Pages[path] = CacheValue{
blt::system::getCurrentTimeNanoseconds(),
std::filesystem::last_write_time(fullPath),
@ -152,28 +218,36 @@ namespace cs
{
if (lexer.hasTemplatePrefix('@'))
{
lexer.consumeTemplatePrefix();
std::string token;
while (!lexer.hasTemplateSuffix()) {
if (!lexer.hasNext()) {
BLT_WARN("Invalid template syntax. EOF occurred before template was fully processed!");
break;
}
token += lexer.consume();
}
lexer.consumeTemplateSuffix();
for (const auto& suffix : valid_file_endings){
if (token.ends_with(suffix)) {
auto path = cs::fs::createWebFilePath(token);
if (path == file){
auto token = lexer.consumeToken();
for (const auto& suffix : valid_file_endings)
{
if (token.ends_with(suffix))
{
if (token == file)
{
BLT_WARN("Recursive load detected!");
BLT_WARN("Caching Engine will ignore this attempt, however, it is recommended that you remove the recursive call.");
BLT_WARN("Caching Engine will ignore this, however, it is recommended that you remove the recursive call.");
BLT_WARN("Detected in file '%s' offending link '%s'", file.c_str(), token.c_str());
break;
}
resolvedSite += fetch(path);
resolvedSite += fetch(token);
break;
}
}
} else if (lexer.hasTemplatePrefix('$'))
{
auto token = lexer.consumeToken();
if (std::find_if(
m_Context.begin(), m_Context.end(),
[&token](auto in) -> bool {
return token == in.first;
}
) == m_Context.end())
{
// unable to find the token, we should throw an error to tell the user! (or admin in this case)
BLT_WARN("Unable to find token '%s'!", token.c_str());
} else
resolvedSite += m_Context[token];
} else
resolvedSite += lexer.consume();
}

View File

@ -13,35 +13,6 @@
namespace cs
{
class LexerSyntaxException : public std::runtime_error
{
public:
explicit LexerSyntaxException(const std::string& token):
std::runtime_error(
"Extended-mustache syntax error! An opening '{{' must be closed by '}}'! (near: '" +
token + "')"
)
{}
};
class LexerException : public std::runtime_error
{
public:
explicit LexerException(const std::string& message):
std::runtime_error("Extended-mustache syntax processing error! " + message)
{}
};
class SyntaxException : public std::runtime_error
{
public:
explicit SyntaxException():
std::runtime_error(
"Extended-mustache syntax error! Static context keys should not contain $"
)
{}
};
std::unique_ptr<HTMLPage> HTMLPage::load(const std::string& path)
{
std::string htmlSource;
@ -72,51 +43,4 @@ namespace cs
HTMLPage::HTMLPage(std::string siteData): m_SiteData(std::move(siteData))
{}
std::string HTMLPage::render(StaticContext& context)
{
std::string processedSiteData = m_SiteData;
std::string buffer;
StringLexer lexer(processedSiteData);
while (lexer.hasNext())
{
if (lexer.hasTemplatePrefix('$'))
{
lexer.consumeTemplatePrefix();
std::string token;
while (!lexer.hasTemplateSuffix())
{
if (!lexer.hasNext())
{
BLT_FATAL("Invalid template syntax. EOF occurred before template was fully processed!");
throw LexerSyntaxException(token);
}
token += lexer.consume();
}
lexer.consumeTemplateSuffix();
if (std::find_if(
context.begin(), context.end(),
[&token](auto in) -> bool {
return token == in.first;
}
) == context.end())
{
// unable to find the token, we should throw an error to tell the user! (or admin in this case)
BLT_WARN("Unable to find token '%s'!", token.c_str());
} else
buffer += context[token];
} else
buffer += lexer.consume();
}
return buffer;
}
void HTMLPage::resolveResources()
{
}
}

View File

@ -138,6 +138,8 @@ crow::response handle_root_page(const site_params& params)
if (cs::isUserLoggedIn(s_clientID, s_clientToken))
{
ctx["_logged_in"] = true;
} else {
ctx["_not_logged_in"] = true;
}
// we don't want to pass all get parameters to the context to prevent leaking information