1
0
Fork 0
mirror of https://github.com/KingDuckZ/kamokan.git synced 2024-11-23 00:33:44 +00:00

Pass the output stream and cgi_env to Response.

Mask the fact that they are globals, because I need
to be able to pass different classes in order to be
able to write unit tests for response classes.
This commit is contained in:
King_DuckZ 2017-05-06 19:48:44 +01:00
parent 8980a1d1ff
commit cd1be59cfa
12 changed files with 81 additions and 28 deletions

View file

@ -32,6 +32,7 @@
#include <fstream>
#include <iterator>
#include <ciso646>
#include <iostream>
//www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4150.pdf
@ -53,8 +54,8 @@ namespace {
}
template <typename T>
std::unique_ptr<tawashi::Response> make_response (const Kakoune::SafePtr<tawashi::SettingsBag>& parSettings) {
return static_cast<std::unique_ptr<tawashi::Response>>(std::make_unique<T>(parSettings));
std::unique_ptr<tawashi::Response> make_response (const Kakoune::SafePtr<tawashi::SettingsBag>& parSettings, const Kakoune::SafePtr<tawashi::cgi::Env>& parCgiEnv) {
return static_cast<std::unique_ptr<tawashi::Response>>(std::make_unique<T>(parSettings, &std::cout, parCgiEnv));
}
void fill_defaults (tawashi::SettingsBag& parSettings) {
@ -100,15 +101,15 @@ int main() {
spdlog::set_level(static_cast<decltype(spdlog::level::trace)>(logging_level._to_integral()));
}
tawashi::cgi::Env cgi_env;
tawashi::ResponseFactory resp_factory(settings);
auto cgi_env = SafeStackObject<tawashi::cgi::Env>();
tawashi::ResponseFactory resp_factory(settings, cgi_env);
SPDLOG_TRACE(statuslog, "Registering makers in the response factory");
resp_factory.register_maker("index.cgi", &make_response<IndexResponse>);
resp_factory.register_maker("", &make_response<IndexResponse>);
resp_factory.register_maker("paste.cgi", &make_response<SubmitPasteResponse>);
resp_factory.register_jolly_maker(&make_response<PastieResponse>);
std::unique_ptr<Response> response = resp_factory.make_response(cgi_env.path_info().substr(1));
std::unique_ptr<Response> response = resp_factory.make_response(cgi_env->path_info().substr(1));
response->send();
return 0;

View file

@ -20,6 +20,7 @@
#include "split_get_vars.hpp"
#include "duckhandy/compatibility.h"
#include "escapist.hpp"
#include "kakoune/safe_ptr.hh"
#include <vector>
#include <string>
#include <boost/utility/string_ref.hpp>
@ -30,7 +31,7 @@
namespace tawashi {
namespace cgi {
class Env {
class Env : public Kakoune::SafeCountable {
public:
struct VersionInfo {
boost::string_ref name;

View file

@ -19,8 +19,12 @@
#include <boost/algorithm/string/replace.hpp>
namespace tawashi {
IndexResponse::IndexResponse (const Kakoune::SafePtr<SettingsBag>& parSettings) :
Response(Response::ContentType, "text/html", parSettings, false)
IndexResponse::IndexResponse (
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv
) :
Response(Response::ContentType, "text/html", parSettings, parStreamOut, parCgiEnv, false)
{
}
} //namespace tawashi

View file

@ -23,7 +23,11 @@
namespace tawashi {
class IndexResponse : public Response {
public:
explicit IndexResponse (const Kakoune::SafePtr<SettingsBag>& parSettings);
IndexResponse (
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv
);
protected:
virtual boost::string_ref page_basename() const override { return boost::string_ref("index"); }

View file

@ -19,6 +19,7 @@
#include "incredis/incredis.hpp"
#include "settings_bag.hpp"
#include "escapist.hpp"
#include "cgi_env.hpp"
#include <ciso646>
#include <srchilite/sourcehighlight.h>
#include <srchilite/langmap.h>
@ -29,8 +30,12 @@ namespace tawashi {
const char g_nolang_token[] = "plaintext";
} //unnamed namespace
PastieResponse::PastieResponse (const Kakoune::SafePtr<SettingsBag>& parSettings) :
Response(Response::ContentType, "text/html", parSettings, true),
PastieResponse::PastieResponse (
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv
) :
Response(Response::ContentType, "text/html", parSettings, parStreamOut, parCgiEnv, true),
m_langmap_dir(parSettings->as<std::string>("langmap_dir")),
m_plain_text(false),
m_syntax_highlight(true)

View file

@ -24,7 +24,11 @@
namespace tawashi {
class PastieResponse : public Response {
public:
explicit PastieResponse (const Kakoune::SafePtr<SettingsBag>& parSettings);
PastieResponse (
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv
);
protected:
virtual boost::string_ref page_basename() const override { return boost::string_ref("text"); }

View file

@ -22,6 +22,7 @@
#include "duckhandy/stringize.h"
#include "pathname/pathname.hpp"
#include "list_highlight_langs.hpp"
#include "cgi_env.hpp"
#include <utility>
#include <cassert>
#include <fstream>
@ -104,14 +105,26 @@ namespace tawashi {
};
} //unnamed namespace
Response::Response (Types parRespType, std::string&& parValue, const Kakoune::SafePtr<SettingsBag>& parSettings, bool parWantRedis) :
Response::Response (
Types parRespType,
std::string&& parValue,
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv,
bool parWantRedis
) :
m_resp_value(std::move(parValue)),
//m_page_basename(fetch_page_basename(m_cgi_env)),
m_cgi_env(parCgiEnv),
m_settings(parSettings),
m_website_root(make_root_path(*parSettings)),
m_resp_type(parRespType),
m_stream_out(parStreamOut),
m_header_sent(false)
{
assert(m_cgi_env);
assert(m_stream_out);
if (parWantRedis) {
m_redis = std::make_unique<redis::IncRedis>(make_incredis(*parSettings));
m_redis->connect();
@ -166,16 +179,16 @@ namespace tawashi {
switch (m_resp_type) {
case ContentType:
SPDLOG_TRACE(statuslog, "Response is a Content-type (data)");
std::cout << "Content-type: " << m_resp_value << "\n\n";
*m_stream_out << "Content-type: " << m_resp_value << "\n\n";
break;
case Location:
SPDLOG_TRACE(statuslog, "Response is a Location (redirect)");
std::cout << "Location: " << m_resp_value << "\n\n";
*m_stream_out << "Location: " << m_resp_value << "\n\n";
break;
}
SPDLOG_TRACE(statuslog, "Rendering in mustache");
std::cout << mstch::render(
*m_stream_out << mstch::render(
on_mustache_retrieve(),
mustache_context,
std::bind(
@ -187,7 +200,7 @@ namespace tawashi {
)
);
SPDLOG_TRACE(statuslog, "Flushing output");
std::cout.flush();
m_stream_out->flush();
}
std::string Response::on_mustache_retrieve() {
@ -195,7 +208,7 @@ namespace tawashi {
}
const cgi::Env& Response::cgi_env() const {
return m_cgi_env;
return *m_cgi_env;
}
void Response::change_type (Types parRespType, std::string&& parValue) {

View file

@ -17,7 +17,6 @@
#pragma once
#include "cgi_env.hpp"
#include "mstch/mstch.hpp"
#include "kakoune/safe_ptr.hh"
#include <string>
@ -32,6 +31,10 @@ namespace redis {
namespace tawashi {
class SettingsBag;
namespace cgi {
class Env;
} //namespace cgi
class Response {
public:
virtual ~Response() noexcept;
@ -48,6 +51,8 @@ namespace tawashi {
Types parRespType,
std::string&& parValue,
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv,
bool parWantRedis
);
const cgi::Env& cgi_env() const;
@ -63,12 +68,13 @@ namespace tawashi {
virtual void on_mustache_prepare (mstch::map& parContext);
virtual std::string on_mustache_retrieve();
cgi::Env m_cgi_env;
std::string m_resp_value;
Kakoune::SafePtr<cgi::Env> m_cgi_env;
Kakoune::SafePtr<SettingsBag> m_settings;
std::string m_website_root;
Types m_resp_type;
std::unique_ptr<redis::IncRedis> m_redis;
std::ostream* m_stream_out;
bool m_header_sent;
};
} //namespace tawashi

View file

@ -17,6 +17,7 @@
#include "response_factory.hpp"
#include "settings_bag.hpp"
#include "cgi_env.hpp"
#include <functional>
#include <boost/container/flat_map.hpp>
@ -28,12 +29,14 @@ namespace tawashi {
Kakoune::SafePtr<SettingsBag> settings;
boost::container::flat_map<std::string, ResponseMakerFunc> makers;
ResponseMakerFunc jolly_maker;
Kakoune::SafePtr<cgi::Env> cgi_env;
};
ResponseFactory::ResponseFactory (const Kakoune::SafePtr<SettingsBag>& parSettings) :
ResponseFactory::ResponseFactory (const Kakoune::SafePtr<SettingsBag>& parSettings, const Kakoune::SafePtr<cgi::Env>& parCgiEnv) :
m_local_data(std::make_unique<LocalData>())
{
m_local_data->settings = parSettings;
m_local_data->cgi_env = parCgiEnv;
}
ResponseFactory::~ResponseFactory() noexcept = default;
@ -43,10 +46,10 @@ namespace tawashi {
auto maker_it = m_local_data->makers.find(std::string(parName.data(), parName.size()));
if (m_local_data->makers.end() != maker_it) {
return maker_it->second(m_local_data->settings);
return maker_it->second(m_local_data->settings, m_local_data->cgi_env);
}
else if (m_local_data->jolly_maker) {
return m_local_data->jolly_maker(m_local_data->settings);
return m_local_data->jolly_maker(m_local_data->settings, m_local_data->cgi_env);
}
else {
assert(false);

View file

@ -24,11 +24,15 @@
namespace tawashi {
class SettingsBag;
namespace cgi {
class Env;
} //namespace cgi
class ResponseFactory {
public:
typedef std::function<std::unique_ptr<Response>(const Kakoune::SafePtr<SettingsBag>&)> ResponseMakerFunc;
typedef std::function<std::unique_ptr<Response>(const Kakoune::SafePtr<SettingsBag>&, const Kakoune::SafePtr<cgi::Env>& parCgiEnv)> ResponseMakerFunc;
explicit ResponseFactory (const Kakoune::SafePtr<SettingsBag>& parSettings);
explicit ResponseFactory (const Kakoune::SafePtr<SettingsBag>& parSettings, const Kakoune::SafePtr<cgi::Env>& parCgiEnv);
~ResponseFactory() noexcept;
std::unique_ptr<Response> make_response(const boost::string_ref& parName);

View file

@ -60,8 +60,12 @@ namespace tawashi {
}
} //unnamed namespace
SubmitPasteResponse::SubmitPasteResponse (const Kakoune::SafePtr<SettingsBag>& parSettings) :
Response(Response::ContentType, "text/plain", parSettings, true)
SubmitPasteResponse::SubmitPasteResponse (
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv
) :
Response(Response::ContentType, "text/plain", parSettings, parStreamOut, parCgiEnv, true)
{
}

View file

@ -25,7 +25,11 @@
namespace tawashi {
class SubmitPasteResponse : public Response {
public:
explicit SubmitPasteResponse (const Kakoune::SafePtr<SettingsBag>& parSettings);
SubmitPasteResponse (
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv
);
protected:
virtual boost::string_ref page_basename() const override { return boost::string_ref("paste"); }