From 4baf70ad0c732777ab508b0ee3b81fff9bfe2e84 Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Sun, 20 Aug 2023 23:48:11 -0400 Subject: [PATCH] cache refinement --- include/crowsite/config.h | 4 +- include/crowsite/site/cache.h | 5 ++ include/crowsite/site/web.h | 56 ------------------ src/crowsite/site/cache.cpp | 108 ++++++++++++++++++++++++++++------ src/crowsite/site/web.cpp | 76 ------------------------ src/main.cpp | 2 + 6 files changed, 100 insertions(+), 151 deletions(-) diff --git a/include/crowsite/config.h b/include/crowsite/config.h index dc01212..786a174 100644 --- a/include/crowsite/config.h +++ b/include/crowsite/config.h @@ -8,8 +8,8 @@ #include #include -#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/" #define MILES_SITE diff --git a/include/crowsite/site/cache.h b/include/crowsite/site/cache.h index cb1012e..116090a 100644 --- a/include/crowsite/site/cache.h +++ b/include/crowsite/site/cache.h @@ -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 { diff --git a/include/crowsite/site/web.h b/include/crowsite/site/web.h index 8268669..a47d914 100644 --- a/include/crowsite/site/web.h +++ b/include/crowsite/site/web.h @@ -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 replacements; @@ -82,16 +36,6 @@ namespace cs { explicit HTMLPage(std::string siteData); public: static std::unique_ptr 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; diff --git a/src/crowsite/site/cache.cpp b/src/crowsite/site/cache.cpp index 34fdd4d..f9fc517 100644 --- a/src/crowsite/site/cache.cpp +++ b/src/crowsite/site/cache.cpp @@ -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(); } diff --git a/src/crowsite/site/web.cpp b/src/crowsite/site/web.cpp index 286739f..30120ed 100644 --- a/src/crowsite/site/web.cpp +++ b/src/crowsite/site/web.cpp @@ -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::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() - { - - } } diff --git a/src/main.cpp b/src/main.cpp index b786452..9ae7561 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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