1
0
Fork 0
mirror of https://github.com/KingDuckZ/kamokan.git synced 2024-11-23 00:33:44 +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();
}
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;
parContext["pastie"] = houdini.escape_html(parPastie);
parContext["pastie"] = houdini.escape_html(parPastie.text);
}
} //namespace kamokan

View file

@ -34,7 +34,7 @@ namespace kamokan {
}
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 bool is_submit_page() const override { return true; }
};

View file

@ -19,6 +19,7 @@
#include "cgi_env.hpp"
#include "settings_bag.hpp"
#include "error_reasons.hpp"
#include "spdlog.hpp"
#include "redis_to_error_reason.hpp"
#include <cassert>
#include <ciso646>
@ -45,7 +46,7 @@ namespace kamokan {
boost::string_view token = get_search_token(cgi_env());
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)
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_lang"] = pastie_lang;
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 {
@ -93,4 +111,8 @@ namespace kamokan {
else
return std::string();
}
boost::string_view GeneralPastieResponse::requested_lang() const {
return boost::string_view();
}
} //namespace kamokan

View file

@ -30,14 +30,21 @@ namespace kamokan {
);
protected:
struct Pastie {
std::string text;
std::string comment;
bool highlighted;
};
bool pastie_not_found() const;
bool token_invalid() const;
virtual boost::string_view requested_lang() const;
private:
virtual tawashi::HttpHeader on_process() override final;
virtual void on_mustache_prepare (mstch::map& parContext) override final;
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;
Storage::RetrievedPastie m_pastie_info;

View file

@ -20,7 +20,6 @@
#include "settings_bag.hpp"
#include "escapist.hpp"
#include "cgi_env.hpp"
#include "spdlog.hpp"
#include "highlight_functions.hpp"
#include <ciso646>
#include <algorithm>
@ -70,42 +69,49 @@ namespace kamokan {
m_plain_text(false),
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() {
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;
if (m_plain_text)
return tawashi::make_header_type_text_utf8();
}
else if (query_str == g_nolang_token) {
m_syntax_highlight = false;
}
else {
m_pastie_lang.clear();
if (not query_str.empty())
m_pastie_lang = query_str;
}
else
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 highlight_comment;
if (m_syntax_highlight) {
processed_pastie = std::move(parPastie);
processed_pastie = std::move(parPastie.text);
}
else {
assert(not parPastie.highlighted);
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) {
SplitHighlightedPastie split = highlight_string(std::move(processed_pastie), m_pastie_lang, settings());
if (parPastie.highlighted) {
assert(not parPastie.comment.empty());
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_lines"] = pastie_to_numbered_lines(
@ -121,4 +127,8 @@ namespace kamokan {
else
return load_mustache();
}
boost::string_view PastieResponse::requested_lang() const {
return m_pastie_lang;
}
} //namespace kamokan

View file

@ -32,11 +32,12 @@ namespace kamokan {
protected:
virtual boost::string_view page_basename() const override { return boost::string_view("pastie"); }
virtual boost::string_view requested_lang() const override;
private:
virtual std::string on_mustache_retrieve() 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; }
std::string m_pastie_lang;

View file

@ -1,14 +1,33 @@
local full_token = KEYS[1]
local result = redis.call("HMGET", full_token, "pastie", "selfdes", "lang")
if false == result[1] then
local requested_lang = ARGV[1]
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")
end
local selfdes = 0
local deleted = 0
if result[2] == "1" then
if pastie_selfdes == "1" then
deleted = redis.call("DEL", full_token)
selfdes = 1
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
Storage::RetrievedPastie::RetrievedPastie() :
pastie(),
lang(),
highlighted(false),
self_destructed(false),
valid_token(false)
{
@ -187,9 +186,15 @@ namespace kamokan {
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;
RetrievedPastie retval;
retval.valid_token = is_valid_token(parToken, parMaxTokenLen);
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));
auto batch = m_redis->command().make_batch();
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();
if (raw_replies.empty())
return retval;
@ -213,8 +222,10 @@ namespace kamokan {
retval.pastie = get_string(pastie_reply[0]);
const redis::RedisInt selfdes = get_integer(pastie_reply[1]);
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.highlighted = static_cast<bool>(get_integer(pastie_reply[3]));
retval.comment = get_string(pastie_reply[5]);
if (selfdes and not deleted) {
auto statuslog = spdlog::get("statuslog");

View file

@ -47,6 +47,8 @@ namespace kamokan {
boost::optional<std::string> pastie;
boost::optional<std::string> lang;
boost::optional<std::string> error;
boost::optional<std::string> comment;
bool highlighted;
bool self_destructed;
bool valid_token;
};
@ -71,7 +73,11 @@ namespace kamokan {
uint32_t parMaxTokenLen
) 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)
const SettingsBag& settings() const;

View file

@ -62,7 +62,11 @@ namespace kamokan {
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(
m_submitted_pasties.begin(),
m_submitted_pasties.end(),

View file

@ -52,7 +52,11 @@ namespace kamokan {
const std::string& parRemoteIP
) 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;