mirror of
https://github.com/KingDuckZ/kamokan.git
synced 2024-11-23 00:33:44 +00:00
Make on_process() return an HttpHeader.
Response type is now decided by on_process' return value.
This commit is contained in:
parent
c5f2bc055a
commit
cdd23d35d0
10 changed files with 280 additions and 75 deletions
|
@ -26,6 +26,7 @@ add_library(${PROJECT_NAME} STATIC
|
|||
tiger.c
|
||||
error_response.cpp
|
||||
tawashi_exception.cpp
|
||||
http_header.cpp
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "enum.h"
|
||||
|
||||
namespace tawashi {
|
||||
BETTER_ENUM(CGIVars, std::size_t,
|
||||
SLOW_ENUM(CGIVars, std::size_t,
|
||||
AUTH_TYPE = 0,
|
||||
CONTENT_LENGTH,
|
||||
CONTENT_TYPE,
|
||||
|
|
153
src/tawashi_implem/http_header.cpp
Normal file
153
src/tawashi_implem/http_header.cpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
/* Copyright 2017, Michele Santullo
|
||||
* This file is part of "tawashi".
|
||||
*
|
||||
* "tawashi" is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* "tawashi" is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with "tawashi". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "http_header.hpp"
|
||||
#include "duckhandy/lexical_cast.hpp"
|
||||
#include "duckhandy/sequence_bt.hpp"
|
||||
#include "sprout/array/array.hpp"
|
||||
#include <utility>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace tawashi {
|
||||
namespace {
|
||||
constexpr const char* get_status_code_desc (HttpStatusCodes parCode) {
|
||||
switch (parCode) {
|
||||
case HttpStatusCodes::Code301_MovedPermanently: return "Moved Permanently";
|
||||
case HttpStatusCodes::Code302_Found: return "Found";
|
||||
case HttpStatusCodes::Code303_SeeOther: return "See Other";
|
||||
case HttpStatusCodes::Code400_BadRequest: return "Bad Request";
|
||||
case HttpStatusCodes::Code403_Forbidden: return "Forbidden";
|
||||
case HttpStatusCodes::Code404_NotFound: return "Not Found";
|
||||
case HttpStatusCodes::Code413_PayloadTooLarge: return "Payload Too Large";
|
||||
case HttpStatusCodes::Code429_TooManyRequests: return "Too Many Requests";
|
||||
case HttpStatusCodes::Code431_RequestHeaderFieldsTooLarge: return "Request Header Fields Too Large";
|
||||
case HttpStatusCodes::Code500_InternalServerError: return "Internal Server Error";
|
||||
case HttpStatusCodes::Code501_NotImplemented: return "Not Implemented";
|
||||
case HttpStatusCodes::Code503_ServiceUnavailable: return "Service Unavailable";
|
||||
}
|
||||
return "INVALID STATUS CODE";
|
||||
}
|
||||
|
||||
inline constexpr uint16_t single_status_code_to_code (const char* parCode) {
|
||||
std::size_t idx = 0;
|
||||
uint16_t ret_num = 0;
|
||||
uint16_t digits = 0;
|
||||
char cur_char = 0;
|
||||
while ((cur_char = parCode[idx++]) and digits < 3) {
|
||||
if (cur_char >= '0' and cur_char <= '9') {
|
||||
uint16_t multip = 1;
|
||||
for (uint16_t z = 1; z < (3 - digits); ++z) {
|
||||
multip *= 10;
|
||||
}
|
||||
ret_num += multip * (cur_char - '0');
|
||||
++digits;
|
||||
}
|
||||
}
|
||||
return ret_num;
|
||||
}
|
||||
|
||||
template <int... Values>
|
||||
inline constexpr sprout::array<uint16_t, sizeof...(Values)> make_status_codes_lookup (dhandy::bt::number_seq<int, Values...>) {
|
||||
return sprout::array<uint16_t, sizeof...(Values)> {
|
||||
single_status_code_to_code(HttpStatusCodes::_names()[Values])...
|
||||
};
|
||||
}
|
||||
|
||||
uint16_t status_code_name_to_num (HttpStatusCodes parCode) {
|
||||
constexpr const auto status_codes = make_status_codes_lookup(dhandy::bt::number_range<int, 0, HttpStatusCodes::_size() - 1>());
|
||||
return status_codes[parCode._to_integral()];
|
||||
}
|
||||
|
||||
constexpr auto g_status_code_descriptions = ::better_enums::make_map(get_status_code_desc);
|
||||
} //unnamed namespace
|
||||
|
||||
HttpHeader::HttpHeader() :
|
||||
m_param("text/html"),
|
||||
m_status_code(HttpStatusCodes::CodeNone),
|
||||
m_header_type(ContentType)
|
||||
{
|
||||
}
|
||||
|
||||
HttpHeader::HttpHeader (Types parType, HttpStatusCodes parCode, std::string&& parParam) :
|
||||
m_param(std::move(parParam)),
|
||||
m_status_code(parCode),
|
||||
m_header_type(parType)
|
||||
{
|
||||
}
|
||||
|
||||
void HttpHeader::set_status (HttpStatusCodes parCode) {
|
||||
m_status_code = parCode;
|
||||
}
|
||||
|
||||
void HttpHeader::unset_status() {
|
||||
m_status_code = HttpStatusCodes::CodeNone;
|
||||
}
|
||||
|
||||
void HttpHeader::set_type (Types parType, std::string&& parParameter) {
|
||||
m_header_type = parType;
|
||||
m_param = std::move(parParameter);
|
||||
}
|
||||
|
||||
std::ostream& operator<< (std::ostream& parStream, const HttpHeader& parHeader) {
|
||||
const HttpStatusCodes code_none = HttpStatusCodes::CodeNone;
|
||||
if (parHeader.status_code() != code_none) {
|
||||
parStream <<
|
||||
"Status: " <<
|
||||
status_code_name_to_num(parHeader.status_code()) <<
|
||||
g_status_code_descriptions[parHeader.status_code()] <<
|
||||
'\n'
|
||||
;
|
||||
}
|
||||
switch (parHeader.type()) {
|
||||
case HttpHeader::ContentType:
|
||||
SPDLOG_TRACE(spdlog::get("statuslog"), "Response is a Content-type (data)");
|
||||
parStream << "Content-type: " << parHeader.parameter() << '\n';
|
||||
break;
|
||||
case HttpHeader::Location:
|
||||
SPDLOG_TRACE(spdlog::get("statuslog"), "Response is a Location (redirect)");
|
||||
parStream << "Location: " << parHeader.parameter() << '\n';
|
||||
break;
|
||||
}
|
||||
parStream << '\n';
|
||||
return parStream;
|
||||
}
|
||||
|
||||
HttpHeader make_header_type_html() {
|
||||
return HttpHeader(HttpHeader::ContentType, HttpStatusCodes::CodeNone, "text/html");
|
||||
}
|
||||
|
||||
HttpHeader make_header_type_text_utf8() {
|
||||
return HttpHeader(HttpHeader::ContentType, HttpStatusCodes::CodeNone, "text/plain; charset=utf-8");
|
||||
}
|
||||
|
||||
HttpStatusCodes int_to_status_code (uint16_t parCode) {
|
||||
constexpr const auto status_codes = make_status_codes_lookup(dhandy::bt::number_range<int, 0, HttpStatusCodes::_size() - 1>());
|
||||
auto it_found_code = std::find(status_codes.begin(), status_codes.end(), parCode);
|
||||
if (it_found_code != status_codes.end()) {
|
||||
const auto index = it_found_code - status_codes.begin();
|
||||
assert(index < HttpStatusCodes::_size() - 1);
|
||||
return HttpStatusCodes::_from_integral(index);
|
||||
}
|
||||
else {
|
||||
return HttpStatusCodes::CodeNone;
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpHeader::body_required() const {
|
||||
return type() == ContentType;
|
||||
}
|
||||
} //namespace tawashi
|
72
src/tawashi_implem/http_header.hpp
Normal file
72
src/tawashi_implem/http_header.hpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Copyright 2017, Michele Santullo
|
||||
* This file is part of "tawashi".
|
||||
*
|
||||
* "tawashi" is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* "tawashi" is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with "tawashi". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "enum.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
namespace tawashi {
|
||||
SLOW_ENUM(HttpStatusCodes, uint16_t,
|
||||
Code301_MovedPermanently,
|
||||
Code302_Found,
|
||||
Code303_SeeOther,
|
||||
Code400_BadRequest,
|
||||
Code403_Forbidden,
|
||||
Code404_NotFound,
|
||||
Code413_PayloadTooLarge,
|
||||
Code429_TooManyRequests,
|
||||
Code431_RequestHeaderFieldsTooLarge,
|
||||
Code500_InternalServerError,
|
||||
Code501_NotImplemented,
|
||||
Code503_ServiceUnavailable,
|
||||
CodeNone
|
||||
)
|
||||
class HttpHeader {
|
||||
public:
|
||||
enum Types : uint8_t {
|
||||
ContentType,
|
||||
Location,
|
||||
Status
|
||||
};
|
||||
|
||||
HttpHeader();
|
||||
HttpHeader (Types parType, HttpStatusCodes parCode, std::string&& parParam);
|
||||
~HttpHeader() noexcept = default;
|
||||
|
||||
Types type() const { return m_header_type; }
|
||||
HttpStatusCodes status_code() const { return m_status_code; }
|
||||
const std::string& parameter() const { return m_param; }
|
||||
bool body_required() const;
|
||||
|
||||
void set_status (HttpStatusCodes parCode);
|
||||
void unset_status();
|
||||
void set_type (Types parType, std::string&& parParameter);
|
||||
|
||||
private:
|
||||
std::string m_param;
|
||||
HttpStatusCodes m_status_code;
|
||||
Types m_header_type;
|
||||
};
|
||||
|
||||
std::ostream& operator<< (std::ostream& parStream, const HttpHeader& parHeader);
|
||||
HttpHeader make_header_type_html();
|
||||
HttpHeader make_header_type_text_utf8();
|
||||
HttpStatusCodes int_to_status_code (uint16_t parCode);
|
||||
} //namespace tawashi
|
|
@ -42,11 +42,11 @@ namespace tawashi {
|
|||
{
|
||||
}
|
||||
|
||||
void PastieResponse::on_process() {
|
||||
HttpHeader PastieResponse::on_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()) {
|
||||
this->change_type(Response::ContentType, "text/plain; charset=utf-8");
|
||||
return make_header_type_text_utf8();
|
||||
m_plain_text = true;
|
||||
}
|
||||
else if (query_str == g_nolang_token) {
|
||||
|
@ -61,6 +61,7 @@ namespace tawashi {
|
|||
if (m_lang_file.empty())
|
||||
m_lang_file = "default.lang";
|
||||
}
|
||||
return make_header_type_html();
|
||||
}
|
||||
|
||||
void PastieResponse::on_mustache_prepare (mstch::map& parContext) {
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace tawashi {
|
|||
virtual boost::string_ref page_basename() const override { return boost::string_ref("pastie"); }
|
||||
|
||||
private:
|
||||
virtual void on_process() override;
|
||||
virtual HttpHeader on_process() override;
|
||||
virtual void on_mustache_prepare (mstch::map& parContext) override;
|
||||
virtual std::string on_mustache_retrieve() override;
|
||||
|
||||
|
|
|
@ -124,13 +124,11 @@ namespace tawashi {
|
|||
const Kakoune::SafePtr<cgi::Env>& parCgiEnv,
|
||||
bool parWantRedis
|
||||
) :
|
||||
m_resp_value(g_def_response_type),
|
||||
//m_page_basename(fetch_page_basename(m_cgi_env)),
|
||||
m_cgi_env(parCgiEnv),
|
||||
m_settings(parSettings),
|
||||
m_website_root(make_root_path(*parSettings)),
|
||||
m_base_uri(make_base_uri(m_settings->at("base_uri"), m_cgi_env->https())),
|
||||
m_resp_type(ContentType),
|
||||
m_stream_out(parStreamOut),
|
||||
m_header_sent(false)
|
||||
{
|
||||
|
@ -155,7 +153,8 @@ namespace tawashi {
|
|||
|
||||
Response::~Response() noexcept = default;
|
||||
|
||||
void Response::on_process() {
|
||||
HttpHeader Response::on_process() {
|
||||
return HttpHeader();
|
||||
}
|
||||
|
||||
void Response::on_mustache_prepare (mstch::map&) {
|
||||
|
@ -183,26 +182,13 @@ namespace tawashi {
|
|||
}
|
||||
|
||||
SPDLOG_TRACE(statuslog, "Raising event on_process");
|
||||
this->on_process();
|
||||
HttpHeader http_header = this->on_process();
|
||||
*m_stream_out << http_header;
|
||||
|
||||
SPDLOG_TRACE(statuslog, "Raising event on_mustache_prepare");
|
||||
this->on_mustache_prepare(mustache_context);
|
||||
|
||||
m_header_sent = true;
|
||||
bool render_page = true;
|
||||
switch (m_resp_type) {
|
||||
case ContentType:
|
||||
SPDLOG_TRACE(statuslog, "Response is a Content-type (data)");
|
||||
*m_stream_out << "Content-type: " << m_resp_value << "\n\n";
|
||||
break;
|
||||
case Location:
|
||||
SPDLOG_TRACE(statuslog, "Response is a Location (redirect)");
|
||||
*m_stream_out << "Status: 303 See Other" << "\n";
|
||||
*m_stream_out << "Location: " << m_resp_value << "\n\n";
|
||||
render_page = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (render_page) {
|
||||
if (http_header.body_required()) {
|
||||
SPDLOG_TRACE(statuslog, "Rendering in mustache");
|
||||
*m_stream_out << mstch::render(
|
||||
on_mustache_retrieve(),
|
||||
|
@ -229,13 +215,6 @@ namespace tawashi {
|
|||
return *m_cgi_env;
|
||||
}
|
||||
|
||||
void Response::change_type (Types parRespType, std::string&& parValue) {
|
||||
assert(not m_header_sent);
|
||||
assert(not parValue.empty());
|
||||
m_resp_type = parRespType;
|
||||
m_resp_value = std::move(parValue);
|
||||
}
|
||||
|
||||
const std::string& Response::base_uri() const {
|
||||
return m_base_uri;
|
||||
}
|
||||
|
@ -254,4 +233,20 @@ namespace tawashi {
|
|||
assert(m_settings);
|
||||
return *m_settings;
|
||||
}
|
||||
|
||||
HttpHeader Response::make_redirect (HttpStatusCodes parCode, const std::string& parLocation) {
|
||||
std::ostringstream oss;
|
||||
oss << base_uri() << '/' << parLocation;
|
||||
return HttpHeader(HttpHeader::Location, parCode, oss.str());
|
||||
}
|
||||
|
||||
HttpHeader Response::make_error_redirect (uint16_t parCode, ErrorReasons parReason) {
|
||||
auto statuslog = spdlog::get("statuslog");
|
||||
assert(statuslog);
|
||||
statuslog->info("Redirecting to error page, code={} reason={}", parCode, parReason);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "error.cgi?code=" << parCode << "&reason=" << parReason._to_integral();
|
||||
return make_redirect(int_to_status_code(parCode), oss.str());
|
||||
}
|
||||
} //namespace tawashi
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "mstch/mstch.hpp"
|
||||
#include "kakoune/safe_ptr.hh"
|
||||
#include "http_header.hpp"
|
||||
#include "error_reasons.hpp"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
@ -42,11 +44,6 @@ namespace tawashi {
|
|||
void send();
|
||||
|
||||
protected:
|
||||
enum Types {
|
||||
ContentType,
|
||||
Location
|
||||
};
|
||||
|
||||
Response (
|
||||
const Kakoune::SafePtr<SettingsBag>& parSettings,
|
||||
std::ostream* parStreamOut,
|
||||
|
@ -54,26 +51,24 @@ namespace tawashi {
|
|||
bool parWantRedis
|
||||
);
|
||||
|
||||
void change_type (Types parRespType, std::string&& parValue);
|
||||
|
||||
const cgi::Env& cgi_env() const;
|
||||
const std::string& base_uri() const;
|
||||
virtual boost::string_ref page_basename() const = 0;
|
||||
redis::IncRedis& redis() const;
|
||||
const SettingsBag& settings() const;
|
||||
virtual std::string load_mustache() const;
|
||||
HttpHeader make_redirect (HttpStatusCodes parCode, const std::string& parLocation);
|
||||
HttpHeader make_error_redirect (uint16_t parCode, ErrorReasons parReason);
|
||||
|
||||
private:
|
||||
virtual void on_process();
|
||||
virtual HttpHeader on_process();
|
||||
virtual void on_mustache_prepare (mstch::map& parContext);
|
||||
virtual std::string on_mustache_retrieve();
|
||||
|
||||
std::string m_resp_value;
|
||||
Kakoune::SafePtr<cgi::Env> m_cgi_env;
|
||||
Kakoune::SafePtr<SettingsBag> m_settings;
|
||||
std::string m_website_root;
|
||||
std::string m_base_uri;
|
||||
Types m_resp_type;
|
||||
std::unique_ptr<redis::IncRedis> m_redis;
|
||||
std::ostream* m_stream_out;
|
||||
bool m_header_sent;
|
||||
|
|
|
@ -97,10 +97,9 @@ namespace tawashi {
|
|||
) :
|
||||
Response(parSettings, parStreamOut, parCgiEnv, true)
|
||||
{
|
||||
this->change_type(Response::ContentType, "text/plain");
|
||||
}
|
||||
|
||||
void SubmitPasteResponse::on_process() {
|
||||
HttpHeader SubmitPasteResponse::on_process() {
|
||||
auto post = cgi::read_post(std::cin, cgi_env());
|
||||
boost::string_ref pastie;
|
||||
boost::string_ref lang;
|
||||
|
@ -114,8 +113,7 @@ namespace tawashi {
|
|||
}
|
||||
catch (const TawashiException& e) {
|
||||
statuslog->error(e.what());
|
||||
error_redirect(500, e.reason());
|
||||
return;
|
||||
return make_error_redirect(500, e.reason());
|
||||
}
|
||||
try {
|
||||
lang = get_value_from_post(post, make_string_ref(g_language_key));
|
||||
|
@ -128,50 +126,51 @@ namespace tawashi {
|
|||
const SettingsBag& settings = this->settings();
|
||||
const auto max_sz = settings.as<uint32_t>("max_pastie_size");
|
||||
if (pastie.size() < settings.as<uint32_t>("min_pastie_size")) {
|
||||
error_redirect(431, ErrorReasons::PostLengthNotInRange);
|
||||
return;
|
||||
return make_error_redirect(431, ErrorReasons::PostLengthNotInRange);
|
||||
}
|
||||
if (max_sz and pastie.size() > max_sz) {
|
||||
if (settings.as<bool>("truncate_long_pasties")) {
|
||||
pastie = pastie.substr(0, max_sz);
|
||||
}
|
||||
else {
|
||||
error_redirect(431, ErrorReasons::PostLengthNotInRange);
|
||||
return;
|
||||
return make_error_redirect(431, ErrorReasons::PostLengthNotInRange);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: replace boost's lexical_cast with mine when I have some checks
|
||||
//over invalid inputs
|
||||
const uint32_t duration_int = std::max(std::min((duration.empty() ? 86400U : boost::lexical_cast<uint32_t>(duration)), 2628000U), 1U);
|
||||
boost::optional<std::string> token = submit_to_redis(pastie, duration_int, lang);
|
||||
StringOrHeader submit_result = submit_to_redis(pastie, duration_int, lang);
|
||||
const auto& token = submit_result.first;
|
||||
|
||||
if (token) {
|
||||
std::ostringstream oss;
|
||||
oss << base_uri() << '/' << *token;
|
||||
oss << *token;
|
||||
statuslog->info("Pastie token=\"{}\" redirect=\"{}\"", *token, oss.str());
|
||||
if (not lang.empty())
|
||||
oss << '?' << lang;
|
||||
this->change_type(Response::Location, oss.str());
|
||||
return this->make_redirect(HttpStatusCodes::CodeNone, oss.str());
|
||||
}
|
||||
else {
|
||||
statuslog->info("Empty pastie token (possibly due to a previous failure)");
|
||||
return;
|
||||
return submit_result.second;
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<std::string> SubmitPasteResponse::submit_to_redis (const boost::string_ref& parText, uint32_t parExpiry, const boost::string_ref& parLang) {
|
||||
auto SubmitPasteResponse::submit_to_redis (
|
||||
const boost::string_ref& parText,
|
||||
uint32_t parExpiry,
|
||||
const boost::string_ref& parLang
|
||||
) -> StringOrHeader {
|
||||
auto& redis = this->redis();
|
||||
if (not redis.is_connected()) {
|
||||
error_redirect(503, ErrorReasons::RedisDisconnected);
|
||||
return boost::optional<std::string>();
|
||||
return std::make_pair(boost::optional<std::string>(), make_error_redirect(503, ErrorReasons::RedisDisconnected));
|
||||
}
|
||||
|
||||
std::string ip_hash = hashed_ip(cgi_env().remote_addr());
|
||||
if (redis.get(ip_hash)) {
|
||||
//please wait and submit again
|
||||
error_redirect(429, ErrorReasons::UserFlooding);
|
||||
return boost::optional<std::string>();
|
||||
return std::make_pair(boost::optional<std::string>(), make_error_redirect(429, ErrorReasons::UserFlooding));
|
||||
}
|
||||
|
||||
const auto next_id = redis.incr("paste_counter");
|
||||
|
@ -185,20 +184,9 @@ namespace tawashi {
|
|||
redis.set(ip_hash, "");
|
||||
redis.expire(ip_hash, settings().as<uint32_t>("resubmit_wait"));
|
||||
if (redis.expire(token, parExpiry))
|
||||
return boost::make_optional(token);
|
||||
return std::make_pair(boost::make_optional(token), HttpHeader());
|
||||
}
|
||||
|
||||
error_redirect(500, ErrorReasons::PastieNotSaved);
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
void SubmitPasteResponse::error_redirect (int parCode, ErrorReasons parReason) {
|
||||
auto statuslog = spdlog::get("statuslog");
|
||||
assert(statuslog);
|
||||
statuslog->info("Redirecting to error page, code={} reason={}", parCode, parReason);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << base_uri() << "/error.cgi?code=" << parCode << "&reason=" << parReason._to_integral();
|
||||
this->change_type(Response::Location, oss.str());
|
||||
return std::make_pair(boost::optional<std::string>(), make_error_redirect(500, ErrorReasons::PastieNotSaved));
|
||||
}
|
||||
} //namespace tawashi
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "response.hpp"
|
||||
#include "error_reasons.hpp"
|
||||
#include <string>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
namespace tawashi {
|
||||
class SubmitPasteResponse : public Response {
|
||||
|
@ -37,8 +37,8 @@ namespace tawashi {
|
|||
virtual boost::string_ref page_basename() const override { assert(false); return boost::string_ref(""); }
|
||||
|
||||
private:
|
||||
virtual void on_process() override;
|
||||
boost::optional<std::string> submit_to_redis (const boost::string_ref& parText, uint32_t parExpiry, const boost::string_ref& parLang);
|
||||
void error_redirect (int parCode, ErrorReasons parReason);
|
||||
typedef std::pair<boost::optional<std::string>, HttpHeader> StringOrHeader;
|
||||
virtual HttpHeader on_process() override;
|
||||
StringOrHeader submit_to_redis (const boost::string_ref& parText, uint32_t parExpiry, const boost::string_ref& parLang);
|
||||
};
|
||||
} //namespace tawashi
|
||||
|
|
Loading…
Reference in a new issue