1
0
Fork 0
mirror of https://github.com/KingDuckZ/kamokan.git synced 2025-06-07 00:51:41 +00:00

Get the pre-cached highlighted pastie if available.

This commit is contained in:
King_DuckZ 2017-08-08 00:09:03 +01:00
parent 5b33417979
commit b7a5ce09e1
11 changed files with 129 additions and 40 deletions

View file

@ -32,8 +32,13 @@ namespace kamokan {
return tawashi::make_header_type_html(); return tawashi::make_header_type_html();
} }
void EditResponse::on_general_mustache_prepare (std::string&& parPastie, mstch::map& parContext) { void EditResponse::on_general_mustache_prepare (
GeneralPastieResponse::Pastie&& parPastie,
mstch::map& parContext
) {
assert(not parPastie.highlighted);
assert(parPastie.comment.empty());
tawashi::Escapist houdini; tawashi::Escapist houdini;
parContext["pastie"] = houdini.escape_html(parPastie); parContext["pastie"] = houdini.escape_html(parPastie.text);
} }
} //namespace kamokan } //namespace kamokan

View file

@ -34,7 +34,7 @@ namespace kamokan {
} }
private: private:
virtual void on_general_mustache_prepare (std::string&& parPastie, mstch::map& parContext) override; virtual void on_general_mustache_prepare (GeneralPastieResponse::Pastie&& parPastie, mstch::map& parContext) override;
virtual tawashi::HttpHeader on_general_pastie_process() override; virtual tawashi::HttpHeader on_general_pastie_process() override;
virtual bool is_submit_page() const override { return true; } virtual bool is_submit_page() const override { return true; }
}; };

View file

@ -19,6 +19,7 @@
#include "cgi_env.hpp" #include "cgi_env.hpp"
#include "settings_bag.hpp" #include "settings_bag.hpp"
#include "error_reasons.hpp" #include "error_reasons.hpp"
#include "spdlog.hpp"
#include "redis_to_error_reason.hpp" #include "redis_to_error_reason.hpp"
#include <cassert> #include <cassert>
#include <ciso646> #include <ciso646>
@ -45,7 +46,7 @@ namespace kamokan {
boost::string_view token = get_search_token(cgi_env()); boost::string_view token = get_search_token(cgi_env());
m_pastie_info = m_pastie_info =
storage().retrieve_pastie(token, settings().as<uint32_t>("max_token_length")); storage().retrieve_pastie(token, settings().as<uint32_t>("max_token_length"), this->requested_lang());
if (m_pastie_info.error) if (m_pastie_info.error)
return make_error_redirect(redis_to_error_reason(*m_pastie_info.error)); return make_error_redirect(redis_to_error_reason(*m_pastie_info.error));
@ -74,8 +75,25 @@ namespace kamokan {
parContext["pastie_token"] = get_search_token(cgi_env()); parContext["pastie_token"] = get_search_token(cgi_env());
parContext["pastie_lang"] = pastie_lang; parContext["pastie_lang"] = pastie_lang;
parContext["colourless"] = pastie_lang.empty() or pastie_lang == "colourless"; parContext["colourless"] = pastie_lang.empty() or pastie_lang == "colourless";
parContext["from_cache"] = m_pastie_info.highlighted;
this->on_general_mustache_prepare(std::move(*m_pastie_info.pastie), parContext); auto statuslog = spdlog::get("statuslog");
SPDLOG_TRACE(
statuslog,
"General mustache response prepared; pastie len={}, comment len={}, highlighted={}",
m_pastie_info.pastie->size(),
(m_pastie_info.comment ? m_pastie_info.comment->size() : 0),
m_pastie_info.highlighted
);
this->on_general_mustache_prepare(
Pastie{
std::move(*m_pastie_info.pastie),
(m_pastie_info.comment ? std::move(*m_pastie_info.comment) : std::string()),
m_pastie_info.highlighted
},
parContext
);
} }
bool GeneralPastieResponse::token_invalid() const { bool GeneralPastieResponse::token_invalid() const {
@ -93,4 +111,8 @@ namespace kamokan {
else else
return std::string(); return std::string();
} }
boost::string_view GeneralPastieResponse::requested_lang() const {
return boost::string_view();
}
} //namespace kamokan } //namespace kamokan

View file

@ -30,14 +30,21 @@ namespace kamokan {
); );
protected: protected:
struct Pastie {
std::string text;
std::string comment;
bool highlighted;
};
bool pastie_not_found() const; bool pastie_not_found() const;
bool token_invalid() const; bool token_invalid() const;
virtual boost::string_view requested_lang() const;
private: private:
virtual tawashi::HttpHeader on_process() override final; virtual tawashi::HttpHeader on_process() override final;
virtual void on_mustache_prepare (mstch::map& parContext) override final; virtual void on_mustache_prepare (mstch::map& parContext) override final;
virtual tawashi::HttpHeader on_general_pastie_process() = 0; virtual tawashi::HttpHeader on_general_pastie_process() = 0;
virtual void on_general_mustache_prepare (std::string&& parPastie, mstch::map& parContext) = 0; virtual void on_general_mustache_prepare (Pastie&& parPastie, mstch::map& parContext) = 0;
std::string default_pastie_lang() override; std::string default_pastie_lang() override;
Storage::RetrievedPastie m_pastie_info; Storage::RetrievedPastie m_pastie_info;

View file

@ -20,7 +20,6 @@
#include "settings_bag.hpp" #include "settings_bag.hpp"
#include "escapist.hpp" #include "escapist.hpp"
#include "cgi_env.hpp" #include "cgi_env.hpp"
#include "spdlog.hpp"
#include "highlight_functions.hpp" #include "highlight_functions.hpp"
#include <ciso646> #include <ciso646>
#include <algorithm> #include <algorithm>
@ -70,41 +69,48 @@ namespace kamokan {
m_plain_text(false), m_plain_text(false),
m_syntax_highlight(true) m_syntax_highlight(true)
{ {
auto get = cgi_env().query_string_split();
const std::string& query_str(cgi_env().query_string());
if (get["m"] == "plain" or query_str.empty())
m_plain_text = true;
else if (query_str == g_nolang_token)
m_syntax_highlight = false;
else if (not query_str.empty())
m_pastie_lang = query_str;
} }
tawashi::HttpHeader PastieResponse::on_general_pastie_process() { tawashi::HttpHeader PastieResponse::on_general_pastie_process() {
auto get = cgi_env().query_string_split(); if (m_plain_text)
const std::string& query_str(cgi_env().query_string());
if (get["m"] == "plain" or query_str.empty()) {
m_plain_text = true;
return tawashi::make_header_type_text_utf8(); return tawashi::make_header_type_text_utf8();
} else
else if (query_str == g_nolang_token) { return tawashi::make_header_type_html();
m_syntax_highlight = false;
}
else {
m_pastie_lang.clear();
if (not query_str.empty())
m_pastie_lang = query_str;
}
return tawashi::make_header_type_html();
} }
void PastieResponse::on_general_mustache_prepare (std::string&& parPastie, mstch::map& parContext) { void PastieResponse::on_general_mustache_prepare (
GeneralPastieResponse::Pastie&& parPastie,
mstch::map& parContext
) {
std::string processed_pastie; std::string processed_pastie;
std::string highlight_comment; std::string highlight_comment;
if (m_syntax_highlight) { if (m_syntax_highlight) {
processed_pastie = std::move(parPastie); processed_pastie = std::move(parPastie.text);
} }
else { else {
assert(not parPastie.highlighted);
tawashi::Escapist houdini; tawashi::Escapist houdini;
processed_pastie = houdini.escape_html(parPastie); processed_pastie = houdini.escape_html(parPastie.text);
} }
if (not m_plain_text and m_syntax_highlight) { if (not m_plain_text and m_syntax_highlight) {
SplitHighlightedPastie split = highlight_string(std::move(processed_pastie), m_pastie_lang, settings()); if (parPastie.highlighted) {
processed_pastie = std::move(split.text); assert(not parPastie.comment.empty());
highlight_comment = std::move(split.comment); highlight_comment = std::move(parPastie.comment);
}
else {
SplitHighlightedPastie split = highlight_string(std::move(processed_pastie), requested_lang(), settings());
processed_pastie = std::move(split.text);
highlight_comment = std::move(split.comment);
}
} }
parContext["pastie"] = std::move(processed_pastie); parContext["pastie"] = std::move(processed_pastie);
@ -121,4 +127,8 @@ namespace kamokan {
else else
return load_mustache(); return load_mustache();
} }
boost::string_view PastieResponse::requested_lang() const {
return m_pastie_lang;
}
} //namespace kamokan } //namespace kamokan

View file

@ -32,11 +32,12 @@ namespace kamokan {
protected: protected:
virtual boost::string_view page_basename() const override { return boost::string_view("pastie"); } virtual boost::string_view page_basename() const override { return boost::string_view("pastie"); }
virtual boost::string_view requested_lang() const override;
private: private:
virtual std::string on_mustache_retrieve() override; virtual std::string on_mustache_retrieve() override;
virtual tawashi::HttpHeader on_general_pastie_process() override; virtual tawashi::HttpHeader on_general_pastie_process() override;
virtual void on_general_mustache_prepare (std::string&& parPastie, mstch::map& parContext) override; virtual void on_general_mustache_prepare (GeneralPastieResponse::Pastie&& parPastie, mstch::map& parContext) override;
virtual bool is_pastie_page() const override { return true; } virtual bool is_pastie_page() const override { return true; }
std::string m_pastie_lang; std::string m_pastie_lang;

View file

@ -1,14 +1,33 @@
local full_token = KEYS[1] local full_token = KEYS[1]
local result = redis.call("HMGET", full_token, "pastie", "selfdes", "lang") local requested_lang = ARGV[1]
if false == result[1] then local pastie_info = redis.call("HMGET", full_token, "lang", "selfdes")
local pastie_lang = pastie_info[1]
local pastie_selfdes = pastie_info[2]
local ret_pastie = false
local ret_comment = ""
local is_highlighted = 0
if pastie_lang == requested_lang then
local result = redis.call("HMGET", full_token, "hl_pastie", "hl_comment")
ret_pastie = result[1]
ret_comment = result[2]
is_highlighted = 1
end
if false == ret_pastie then
local result = redis.call("HMGET", full_token, "pastie")
ret_pastie = result[1]
is_highlighted = 0
end
if false == ret_pastie then
return redis.error_reply("PastieNotFound") return redis.error_reply("PastieNotFound")
end end
local selfdes = 0 local selfdes = 0
local deleted = 0 local deleted = 0
if result[2] == "1" then if pastie_selfdes == "1" then
deleted = redis.call("DEL", full_token) deleted = redis.call("DEL", full_token)
selfdes = 1 selfdes = 1
end end
return {result[1], selfdes, deleted, result[3]} return {ret_pastie, selfdes, deleted, is_highlighted, pastie_lang, ret_comment}

View file

@ -92,8 +92,7 @@ namespace kamokan {
} //unnamed namespace } //unnamed namespace
Storage::RetrievedPastie::RetrievedPastie() : Storage::RetrievedPastie::RetrievedPastie() :
pastie(), highlighted(false),
lang(),
self_destructed(false), self_destructed(false),
valid_token(false) valid_token(false)
{ {
@ -187,9 +186,15 @@ namespace kamokan {
return make_submission_result(std::move(token)); return make_submission_result(std::move(token));
} }
auto Storage::retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const -> RetrievedPastie { auto Storage::retrieve_pastie (
const boost::string_view& parToken,
uint32_t parMaxTokenLen,
const boost::string_view& parRequestedLang
) const -> RetrievedPastie {
using boost::string_view; using boost::string_view;
RetrievedPastie retval; RetrievedPastie retval;
retval.valid_token = is_valid_token(parToken, parMaxTokenLen); retval.valid_token = is_valid_token(parToken, parMaxTokenLen);
if (not retval.valid_token) if (not retval.valid_token)
@ -198,7 +203,11 @@ namespace kamokan {
redis::Script retrieve = m_redis->command().make_script(string_view(g_load_script, g_load_script_size)); redis::Script retrieve = m_redis->command().make_script(string_view(g_load_script, g_load_script_size));
auto batch = m_redis->command().make_batch(); auto batch = m_redis->command().make_batch();
std::string token_with_prefix = make_regular_pastie_token(parToken); std::string token_with_prefix = make_regular_pastie_token(parToken);
retrieve.run(batch, std::make_tuple(token_with_prefix), std::tuple<>()); retrieve.run(
batch,
std::make_tuple(token_with_prefix),
std::make_tuple(parRequestedLang)
);
auto raw_replies = batch.replies(); auto raw_replies = batch.replies();
if (raw_replies.empty()) if (raw_replies.empty())
return retval; return retval;
@ -213,8 +222,10 @@ namespace kamokan {
retval.pastie = get_string(pastie_reply[0]); retval.pastie = get_string(pastie_reply[0]);
const redis::RedisInt selfdes = get_integer(pastie_reply[1]); const redis::RedisInt selfdes = get_integer(pastie_reply[1]);
const redis::RedisInt deleted = get_integer(pastie_reply[2]); const redis::RedisInt deleted = get_integer(pastie_reply[2]);
retval.lang = get_string(pastie_reply[3]); retval.lang = get_string(pastie_reply[4]);
retval.self_destructed = selfdes and deleted; retval.self_destructed = selfdes and deleted;
retval.highlighted = static_cast<bool>(get_integer(pastie_reply[3]));
retval.comment = get_string(pastie_reply[5]);
if (selfdes and not deleted) { if (selfdes and not deleted) {
auto statuslog = spdlog::get("statuslog"); auto statuslog = spdlog::get("statuslog");

View file

@ -47,6 +47,8 @@ namespace kamokan {
boost::optional<std::string> pastie; boost::optional<std::string> pastie;
boost::optional<std::string> lang; boost::optional<std::string> lang;
boost::optional<std::string> error; boost::optional<std::string> error;
boost::optional<std::string> comment;
bool highlighted;
bool self_destructed; bool self_destructed;
bool valid_token; bool valid_token;
}; };
@ -71,7 +73,11 @@ namespace kamokan {
uint32_t parMaxTokenLen uint32_t parMaxTokenLen
) const; ) const;
kamokan_virtual_testing RetrievedPastie retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const; kamokan_virtual_testing RetrievedPastie retrieve_pastie (
const boost::string_view& parToken,
uint32_t parMaxTokenLen,
const boost::string_view& parRequestedLang
) const;
#if defined(KAMOKAN_WITH_TESTING) #if defined(KAMOKAN_WITH_TESTING)
const SettingsBag& settings() const; const SettingsBag& settings() const;

View file

@ -62,7 +62,11 @@ namespace kamokan {
return submission_res; return submission_res;
} }
Storage::RetrievedPastie FakeStorage::retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const { Storage::RetrievedPastie FakeStorage::retrieve_pastie (
const boost::string_view& parToken,
uint32_t parMaxTokenLen,
const boost::string_view& parLang
) const {
auto it_found = std::find_if( auto it_found = std::find_if(
m_submitted_pasties.begin(), m_submitted_pasties.begin(),
m_submitted_pasties.end(), m_submitted_pasties.end(),

View file

@ -52,7 +52,11 @@ namespace kamokan {
const std::string& parRemoteIP const std::string& parRemoteIP
) const override; ) const override;
kamokan_virtual_testing Storage::RetrievedPastie retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const override; kamokan_virtual_testing Storage::RetrievedPastie retrieve_pastie (
const boost::string_view& parToken,
uint32_t parMaxTokenLen,
const boost::string_view& parLang
) const override;
const std::vector<SubmittedPastie>& submitted_pasties() const; const std::vector<SubmittedPastie>& submitted_pasties() const;