summaryrefslogtreecommitdiff
path: root/project2/cgi
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2013-07-05 00:01:26 +0000
committerrandomdan <randomdan@localhost>2013-07-05 00:01:26 +0000
commit530d921225b019130585667d91bad25194179310 (patch)
tree6f3a750f79ad26047ff5322522219798d19aa64c /project2/cgi
parentMove remaining options out of environment (diff)
downloadproject2-530d921225b019130585667d91bad25194179310.tar.bz2
project2-530d921225b019130585667d91bad25194179310.tar.xz
project2-530d921225b019130585667d91bad25194179310.zip
Massive refactor to remove the appEngine and environment complication and instead have an execution context that's passed around from the original call site
Diffstat (limited to 'project2/cgi')
-rw-r--r--project2/cgi/Jamfile.jam1
-rw-r--r--project2/cgi/cgiAppEngine.cpp242
-rw-r--r--project2/cgi/cgiAppEngine.h92
-rw-r--r--project2/cgi/cgiCommon.cpp70
-rw-r--r--project2/cgi/cgiCommon.h6
-rw-r--r--project2/cgi/cgiContentNegotiate.cpp8
-rw-r--r--project2/cgi/cgiEnvironment.cpp207
-rw-r--r--project2/cgi/cgiEnvironment.h78
-rw-r--r--project2/cgi/cgiProgRouter.cpp13
-rw-r--r--project2/cgi/cgiRequestContext.cpp161
-rw-r--r--project2/cgi/cgiRequestContext.h68
-rw-r--r--project2/cgi/cgiRequestID.cpp11
-rw-r--r--project2/cgi/cgiResultStatic.cpp2
-rw-r--r--project2/cgi/cgiResultWritable.cpp4
-rw-r--r--project2/cgi/cgiRouter.h1
-rw-r--r--project2/cgi/cgiSimpleRouter.cpp2
-rw-r--r--project2/cgi/cgiStageCacheHit.cpp6
-rw-r--r--project2/cgi/cgiStageCustomError.cpp18
-rw-r--r--project2/cgi/cgiStageCustomNotFound.cpp16
-rw-r--r--project2/cgi/cgiStageDefaultError.cpp18
-rw-r--r--project2/cgi/cgiStageDefaultNotFound.cpp10
-rw-r--r--project2/cgi/cgiStageFail.cpp10
-rw-r--r--project2/cgi/cgiStageInitial.cpp13
-rw-r--r--project2/cgi/cgiStagePresent.cpp32
-rw-r--r--project2/cgi/cgiStageRedirect.cpp10
-rw-r--r--project2/cgi/cgiStageRequest.cpp18
-rw-r--r--project2/cgi/cgiUriParam.cpp9
-rw-r--r--project2/cgi/p2webCgi.cpp11
-rw-r--r--project2/cgi/p2webFCgi.cpp11
-rw-r--r--project2/cgi/pch.hpp8
-rw-r--r--project2/cgi/testCgi.cpp22
31 files changed, 568 insertions, 610 deletions
diff --git a/project2/cgi/Jamfile.jam b/project2/cgi/Jamfile.jam
index cf6e55c..8da2f11 100644
--- a/project2/cgi/Jamfile.jam
+++ b/project2/cgi/Jamfile.jam
@@ -57,4 +57,3 @@ exe testCgi :
<library>p2cgicommon
<include>../../libmisc
;
-
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp
index 75bc004..2a82595 100644
--- a/project2/cgi/cgiAppEngine.cpp
+++ b/project2/cgi/cgiAppEngine.cpp
@@ -3,45 +3,83 @@
#include "cgiResult.h"
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHeader.h>
-#include "cgiEnvironment.h"
+#include <cgicc/HTTPStatusHeader.h>
+#include "cgiRequestContext.h"
#include "iterate.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include "ostreamWrapper.h"
#include "scopeObject.h"
+#include "logger.h"
#include <boost/date_time/microsec_time_clock.hpp>
#include <boost/uuid/uuid_io.hpp>
-#include <boost/uuid/uuid_generators.hpp>
#include <boost/lexical_cast.hpp>
+#include <glibmm/exception.h>
+#include <cxxabi.h>
-const std::string SESSIONID = "sessionID";
typedef boost::uuids::uuid SIDKey;
typedef std::string SValue;
SimpleMessageException(UnknownDomain);
-CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) :
- _env(e),
- sessionsContainer(SessionContainerLoader::getFor(e->sessionModule)->create()),
- IO(io),
- outputCachingActive(false)
-{
- try {
- cursession = sessionsContainer->GetSession(boost::uuids::string_generator()(e->getCookieValue(SESSIONID)));
- }
- catch (const NoSuchCookie &) {
- cursession = sessionsContainer->GetSession(boost::uuids::uuid());
- }
-}
+std::string CgiApplicationEngine::dumpdatadoc;
+Glib::ustring CgiApplicationEngine::errorContentType;
+Glib::ustring CgiApplicationEngine::errorTransformStyle;
+std::string CgiApplicationEngine::defaultPresent;
+std::string CgiApplicationEngine::transformContentType;
+std::string CgiApplicationEngine::transformTargetType;
+std::string CgiApplicationEngine::presentRoot;
+std::string CgiApplicationEngine::requestRoot;
+std::string CgiApplicationEngine::errorPresentRoot;
+std::string CgiApplicationEngine::notFoundPresent;
+std::string CgiApplicationEngine::onErrorPresent;
+std::string CgiApplicationEngine::defaultPresenter;
+SessionContainerPtr CgiApplicationEngine::sessionsContainer;
+std::string CgiApplicationEngine::sessionCookie;
+boost::shared_ptr<RouterLoader> CgiApplicationEngine::router;
+boost::intrusive_ptr<HostnamePlatformIdentifier> CgiApplicationEngine::hpi;
-CgiApplicationEngine::~CgiApplicationEngine()
+DECLARE_OPTIONS(CgiApplicationEngine, "Project2 CGI options")
+("cgi.defaultPresenter", Options::value(&defaultPresenter, "xml"),
+ "The default engine for formatting presentations")
+("cgi.transformContentType", Options::value(&transformContentType, "text/xml-xslt"),
+ "The content type specified to enable standard internal transformations")
+("cgi.transformTargetType", Options::value(&transformTargetType, "htmldocument"),
+ "The transform target type used in standard internal transformations")
+("cgi.defaultPresent", Options::value(&defaultPresent, "index"),
+ "The present script to use when no other is specified")
+("cgi.presentRoot", Options::value(&presentRoot, "present"),
+ "The folder in which to find presentation scripts")
+("cgi.requestRoot", Options::value(&requestRoot, "request"),
+ "The folder in which to find request scripts")
+("cgi.errorPresentRoot", Options::value(&errorPresentRoot, "error"),
+ "The folder in which to find presentation scripts for error handling")
+("cgi.errorContentType", Options::value(&errorContentType, "application/xml"),
+ "The Content-Type to use in HTTP headers in event of an error")
+("cgi.errorTransformStyle", Options::value(&errorTransformStyle),
+ "The xml-stylesheet to specify in the data document in event of an error")
+("cgi.notFoundPresent", Options::value(&notFoundPresent),
+ "The present script to use when the requested script does not exist")
+("cgi.onErrorPresent", Options::value(&onErrorPresent),
+ "The present script to use when the requested script (or child) fails")
+("cgi.dumpDataDoc", Options::value(&dumpdatadoc),
+ "Write a copy of the data document before sending it to the web server")
+("cgi.sessionModule", Options::function([](const VariableType & m) { sessionsContainer = SessionContainerLoader::createNew(m); }, "xml"),
+ "The module with which to implement session management")
+("cgi.sessionCookie", Options::value(&sessionCookie, "sessionID"),
+ "The name of the cookie for storing session IDs")
+("cgi.hostRegex", (hpi = new HostnamePlatformIdentifier()),
+ "Regular expression used to define a hostname -> platform association")
+("cgi.router", Options::function([](const VariableType & r) { router = RouterLoader::getFor(r); }, "simple"),
+ "Implemenation of router model to map request paths to scripts")
+END_OPTIONS(CgiApplicationEngine);
+
+CgiApplicationEngine::CgiApplicationEngine()
{
}
-const CgiEnvironment *
-CgiApplicationEngine::env() const
+CgiApplicationEngine::~CgiApplicationEngine()
{
- return _env;
}
TransformSourcePtr
@@ -61,51 +99,51 @@ finalTransformSource(TransformSourcePtr ts)
}
void
-CgiApplicationEngine::process() const
+CgiApplicationEngine::processRun(std::ostream & IO, CgiRequestContext * crc) const
{
- bool sessionEmpty = cursession->Empty();
- startTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
+ bool sessionEmpty = crc->getSession()->Empty();
+ crc->startTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
bool triedNotFound = false;
bool triedOnError = false;
NextStage currentStage = NextStage(new InitialStage());
do {
try {
- currentStage = currentStage.get<0>()->run();
+ currentStage = currentStage.get<0>()->run(crc);
}
catch (const CheckHost::CheckFailure & cf) {
- currentStage = NextStage(new PresentStage(ScriptReader::resolveScript(_env->presentRoot, cf.failedCheck->present(), false)));
+ currentStage = NextStage(new PresentStage(ScriptReader::resolveScript(presentRoot, cf.failedCheck->present(crc), false), crc));
}
catch (const ScriptNotFound & nf) {
- if (_env->notFoundPresent.empty() || triedNotFound) {
+ if (notFoundPresent.empty() || triedNotFound) {
currentStage = NextStage(new DefaultNotFoundStage(nf));
}
else {
triedNotFound = true;
- currentStage = NextStage(new CustomNotFoundStage(nf, ScriptReader::resolveScript(_env->errorPresentRoot, _env->notFoundPresent, false)));
+ currentStage = NextStage(new CustomNotFoundStage(nf, ScriptReader::resolveScript(errorPresentRoot, notFoundPresent, false), crc));
}
}
catch (const std::exception & ex) {
- if (_env->onErrorPresent.empty() || triedOnError) {
- currentStage = NextStage(new DefaultErrorStage(ex));
+ if (onErrorPresent.empty() || triedOnError) {
+ currentStage = NextStage(new DefaultErrorStage(ex, crc));
}
else {
triedNotFound = true;
- currentStage = NextStage(new CustomErrorStage(ex, ScriptReader::resolveScript(_env->errorPresentRoot, _env->onErrorPresent, false)));
+ currentStage = NextStage(new CustomErrorStage(ex, ScriptReader::resolveScript(errorPresentRoot, onErrorPresent, false), crc));
}
}
} while (currentStage.get<0>());
- endTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
+ crc->endTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
ResponseStagePtr rs = currentStage.get<1>();
- outputCachingActive = !rs->caches.empty();
+ bool outputCachingActive = !rs->caches.empty();
if (const MultiRowSetPresenter * p = currentStage.get<3>().get()) {
- addAppData(p, rs->outputOptions);
- addEnvData(p, rs->outputOptions);
+ addAppData(p, rs->outputOptions, crc, outputCachingActive);
+ addEnvData(p, rs->outputOptions, crc, outputCachingActive);
}
- HttpHeaderPtr header = rs->getHeader();
- if (!sessionEmpty || !cursession->Empty()) {
- sessionsContainer->SaveSession(cursession);
- header->setCookie(cgicc::HTTPCookie(SESSIONID, boost::lexical_cast<std::string>(cursession->ID()), "Session ID",
- _env->getServerName().substr(_env->getServerName().find(".")), SessionContainer::sessionTimeOut, "/", false));
+ HttpHeaderPtr header = rs->getHeader(crc);
+ if (!sessionEmpty || !crc->getSession()->Empty()) {
+ sessionsContainer->SaveSession(crc->getSession());
+ header->setCookie(cgicc::HTTPCookie(sessionCookie, boost::lexical_cast<std::string>(crc->getSession()->ID()), "Session ID",
+ crc->getServerName().substr(crc->getServerName().find(".")), SessionContainer::sessionTimeOut, "/", false));
}
if (TransformSourcePtr ts = currentStage.get<2>()) {
TransformSourcePtr final = finalTransformSource(ts);
@@ -113,10 +151,10 @@ CgiApplicationEngine::process() const
boost::shared_ptr<std::fstream> ddd;
ostreamWrapper * osw = NULL;
ScopeObject removeDdd([ts, &osw] { if (osw) { ts->removeTarget(osw); } });
- if (!_env->dumpdatadoc.empty()) {
- ddd = boost::shared_ptr<std::fstream>(new std::fstream(_env->dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out));
+ if (!dumpdatadoc.empty()) {
+ ddd = boost::shared_ptr<std::fstream>(new std::fstream(dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out));
if (ddd->good()) {
- ts->addTarget(osw = new ostreamWrapper(*ddd));
+ ts->addTarget(osw = new ostreamWrapper(*ddd), crc, NULL);
}
else {
ddd.reset();
@@ -124,23 +162,23 @@ CgiApplicationEngine::process() const
}
if (outputCachingActive) {
BOOST_FOREACH(const PresenterCachePtr & p, rs->caches) {
- final->addTarget(p, NULL);
+ final->addTarget(p, crc, NULL);
}
- ts->doTransforms();
+ ts->doTransforms(crc);
BOOST_FOREACH(const PresenterCachePtr & p, rs->caches) {
p->flushCache();
}
- if (rs->caches.front()->check(0)) {
+ if (rs->caches.front()->check(0, crc)) {
ScopeObject emptyFinal([rs] { rs->caches.front()->clearTargets(); });
rs->caches.front()->addTarget(new CgiResult(header, IO,
- rs && rs->outputOptions ? rs->outputOptions->Encoding().as<std::string>() : OutputOptions::encoding), NULL);
- rs->caches.front()->doTransforms();
+ rs && rs->outputOptions ? rs->outputOptions->Encoding(crc).as<std::string>() : OutputOptions::encoding), crc, NULL);
+ rs->caches.front()->doTransforms(crc);
return;
}
}
final->addTarget(new CgiResult(header, IO,
- rs && rs->outputOptions ? rs->outputOptions->Encoding().as<std::string>() : OutputOptions::encoding), NULL);
- ts->doTransforms();
+ rs && rs->outputOptions ? rs->outputOptions->Encoding(crc).as<std::string>() : OutputOptions::encoding), crc, NULL);
+ ts->doTransforms(crc);
}
else {
header->render(IO);
@@ -151,44 +189,38 @@ CgiApplicationEngine::Stage::~Stage()
{
}
-const CgiEnvironment *
-CgiApplicationEngine::Stage::env() const
-{
- return dynamic_cast<const CgiEnvironment *>(Environment::getCurrent());
-}
-
void
-CgiApplicationEngine::addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o) const
+CgiApplicationEngine::addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext * crc, bool outputCachingActive) const
{
- if (!o || o->Environment()) {
+ if (!o || o->Environment(crc)) {
// Environment set up by web server
p->addNewRowSet("environment", Scripts::scriptNamespacePrefix);
// Server stuff
- addEnvToPresenter(p, "servername", &cgicc::CgiEnvironment::getServerName);
- addEnvToPresenter(p, "serversoftware", &cgicc::CgiEnvironment::getServerSoftware);
- addEnvToPresenter(p, "serverprotocol", &cgicc::CgiEnvironment::getServerProtocol);
- addEnvToPresenter(p, "serverport", &cgicc::CgiEnvironment::getServerPort);
- addEnvToPresenter(p, "serverhttps", &cgicc::CgiEnvironment::usingHTTPS);
+ addEnvToPresenter(p, "servername", &cgicc::CgiEnvironment::getServerName, crc);
+ addEnvToPresenter(p, "serversoftware", &cgicc::CgiEnvironment::getServerSoftware, crc);
+ addEnvToPresenter(p, "serverprotocol", &cgicc::CgiEnvironment::getServerProtocol, crc);
+ addEnvToPresenter(p, "serverport", &cgicc::CgiEnvironment::getServerPort, crc);
+ addEnvToPresenter(p, "serverhttps", &cgicc::CgiEnvironment::usingHTTPS, crc);
// Request stuff
if (!outputCachingActive) {
- addEnvToPresenter(p, "referrer", &cgicc::CgiEnvironment::getReferrer);
- addEnvToPresenter(p, "querystring", &cgicc::CgiEnvironment::getQueryString);
+ addEnvToPresenter(p, "referrer", &cgicc::CgiEnvironment::getReferrer, crc);
+ addEnvToPresenter(p, "querystring", &cgicc::CgiEnvironment::getQueryString, crc);
}
p->finishRowSet();
}
- if (!o || o->URL()) {
+ if (!o || o->URL(crc)) {
// URL elements
p->addNewRowSet("uriElems", Scripts::scriptNamespacePrefix);
- p->addAttribute("full", _env->getRedirectURL());
- _env->router->present(p);
+ p->addAttribute("full", crc->getRedirectURL());
+ crc->router->present(p);
p->finishRowSet();
}
- if (!o || o->Parameters()) {
+ if (!o || o->Parameters(crc)) {
// Parameters
p->addNewRowSet("params", Scripts::scriptNamespacePrefix);
- BOOST_FOREACH(cgicc::FormEntry fe, _env->cgi->getElements()) {
+ BOOST_FOREACH(cgicc::FormEntry fe, crc->cgi.getElements()) {
p->addNamedValue(fe.getName(), fe.getValue());
}
p->finishRowSet();
@@ -202,34 +234,78 @@ CgiApplicationEngine::addVarToPresenter(const MultiRowSetPresenter * p, const Gl
}
void
-CgiApplicationEngine::addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o) const
+CgiApplicationEngine::addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext * crc, bool outputCachingActive) const
{
- if (!o || o->Core()) {
- addCoreAppData(p);
+ if (!o || o->Core(crc)) {
+ crc->addContextData(p);
}
- if (!outputCachingActive && (!cursession->Empty()) && (!o || o->Session())) {
+ if (!outputCachingActive && (!crc->getSession()->Empty()) && (!o || o->Session(crc))) {
// Sessions variables
p->addNewRowSet("session", Scripts::scriptNamespacePrefix);
- p->addAttribute("id", boost::lexical_cast<Glib::ustring>(cursession->ID()));
- cursession->ForeachValue(boost::bind(&CgiApplicationEngine::addVarToPresenter, this, p, _1, _2));
+ p->addAttribute("id", boost::lexical_cast<Glib::ustring>(crc->getSession()->ID()));
+ crc->getSession()->ForeachValue(boost::bind(&CgiApplicationEngine::addVarToPresenter, this, p, _1, _2));
p->finishRowSet();
}
- if (!outputCachingActive && (!o || o->Timing())) {
+ if (!outputCachingActive && (!o || o->Timing(crc))) {
// Timing info
p->addNewRowSet("timing", Scripts::scriptNamespacePrefix);
- p->addAttribute("start", startTime);
- if (!endTime.is_not_a_date_time()) {
- p->addAttribute("end", endTime);
- p->addAttribute("duration", (endTime - startTime).total_milliseconds());
+ p->addAttribute("start", crc->startTime);
+ if (!crc->endTime.is_not_a_date_time()) {
+ p->addAttribute("end", crc->endTime);
+ p->addAttribute("duration", (crc->endTime - crc->startTime).total_milliseconds());
}
p->finishRowSet();
}
}
-SessionPtr
-CgiApplicationEngine::session() const
+const char *
+what(const Glib::Exception & e)
+{
+ return e.what().c_str();
+}
+const char *
+what(const std::exception & e)
{
- return cursession;
+ return e.what();
+}
+template <typename E>
+void
+doExceptionReporting(const E & e, std::ostream & IO)
+{
+ char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL);
+ Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, what(e));
+ cgicc::HTTPStatusHeader header(500, e.what());
+ header.render(IO);
+ IO << "Kaboom!" << std::endl
+ << std::endl
+ << buf << std::endl
+ << "what '" << e.what() << "'" << std::endl;
+ free(buf);
+}
+
+void
+CgiApplicationEngine::process(std::ostream & IO, CgiRequestContext * crc) const
+{
+ try {
+ Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__);
+ processRun(IO, crc);
+ Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__);
+ }
+ catch (const std::exception & e) {
+ doExceptionReporting(e, IO);
+ }
+ catch (const Glib::Exception & e) {
+ doExceptionReporting(e, IO);
+ }
+ catch (...) {
+ Logger()->messagef(LOG_ERR, "%s: Request errored: Unknown exception", __FUNCTION__);
+ cgicc::HTTPStatusHeader header(500, "Unknown exception");
+ header.render(IO);
+ IO << "Kaboom!" << std::endl
+ << std::endl
+ << "Unknown exception." << std::endl;
+ throw;
+ }
}
diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h
index f5f0e08..6d3cd0c 100644
--- a/project2/cgi/cgiAppEngine.h
+++ b/project2/cgi/cgiAppEngine.h
@@ -1,7 +1,6 @@
#ifndef CGIAPPENGINE_H
#define CGIAPPENGINE_H
-#include "appEngine.h"
#include "task.h"
#include "commonObjects.h"
#include "taskHost.h"
@@ -15,7 +14,7 @@
#include <boost/tuple/tuple.hpp>
#include "cgiOutputOptions.h"
#include "cgiHttpHeader.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include <cgicc/Cgicc.h>
class Session;
@@ -24,29 +23,26 @@ namespace cgicc {
class CgiEnvironment;
}
-class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink {
+class CgiApplicationEngine {
public:
typedef boost::shared_ptr<Project2HttpHeader> HttpHeaderPtr;
- CgiApplicationEngine(const CgiEnvironment *, std::ostream &);
+ CgiApplicationEngine();
virtual ~CgiApplicationEngine();
- void process() const;
- const CgiEnvironment * env() const;
- SessionPtr session() const;
- void addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr) const;
- void addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr) const;
+ void process(std::ostream & IO, CgiRequestContext *) const;
private:
- const CgiEnvironment * _env;
- mutable boost::posix_time::ptime startTime;
- mutable boost::posix_time::ptime endTime;
- SessionContainerPtr sessionsContainer;
+ void processRun(std::ostream & IO, CgiRequestContext *) const;
+ void addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext *, bool) const;
+ void addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext *, bool) const;
+
// Helpers
+ //
void addVarToPresenter(const MultiRowSetPresenter * p, const Glib::ustring & name, const VariableType &) const;
template <class X, class Y>
- void addEnvToPresenter(const MultiRowSetPresenter * p, const char * name, X (Y::*getter)() const) const {
- addVarToPresenter(p, name, (_env->cgi->getEnvironment().*getter)());
+ void addEnvToPresenter(const MultiRowSetPresenter * p, const char * name, X (Y::*getter)() const, CgiRequestContext * crc) const {
+ addVarToPresenter(p, name, (crc->cgi.getEnvironment().*getter)());
}
public:
@@ -59,9 +55,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
class Stage : public virtual IntrusivePtrBase {
public:
virtual ~Stage() = 0;
- virtual NextStage run() = 0;
- protected:
- const CgiEnvironment * env() const;
+ virtual NextStage run(CgiRequestContext *) = 0;
};
/// Base class for a stage that can be a response to the client
@@ -70,7 +64,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
typedef ANONORDEREDSTORAGEOF(PresenterCache) PresenterCaches;
ResponseStage(ScriptNodePtr root);
- virtual HttpHeaderPtr getHeader() const = 0;
+ virtual HttpHeaderPtr getHeader(CgiRequestContext *) const = 0;
OutputOptionsPtr outputOptions;
ScriptNodePtr root;
@@ -80,7 +74,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
/// Stage implementation used to bootstrap the iteration process based on the CGI environment
class InitialStage : public Stage {
public:
- virtual NextStage run();
+ virtual NextStage run(CgiRequestContext *);
};
/// Stage to process POST requests
@@ -88,8 +82,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
public:
RequestStage(ScriptReaderPtr);
- virtual NextStage run();
- virtual HttpHeaderPtr getHeader() const;
+ virtual NextStage run(CgiRequestContext *);
+ virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
protected:
Variable present;
Variable redirect;
@@ -98,11 +92,11 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
/// Stage to process GET requests and follow up RequestStages
class PresentStage : public virtual ResponseStage, ViewHost {
public:
- PresentStage(ScriptReaderPtr);
- MultiRowSetPresenterPtr getPresenter() const;
+ PresentStage(ScriptReaderPtr, CgiRequestContext *);
+ MultiRowSetPresenterPtr getPresenter(ExecContext *) const;
- virtual NextStage run();
- virtual HttpHeaderPtr getHeader() const;
+ virtual NextStage run(CgiRequestContext *);
+ virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
protected:
HttpHeaderPtr header;
LazyPointer<MultiRowSetPresenter> presenter;
@@ -113,8 +107,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
public:
CacheHitStage(ScriptNodePtr, PresenterCachePtr);
- virtual NextStage run();
- virtual HttpHeaderPtr getHeader() const;
+ virtual NextStage run(CgiRequestContext *);
+ virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
protected:
PresenterCachePtr pc;
};
@@ -124,8 +118,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
public:
DefaultNotFoundStage(const ScriptNotFound &);
- virtual NextStage run();
- virtual HttpHeaderPtr getHeader() const;
+ virtual NextStage run(CgiRequestContext *);
+ virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
private:
const ScriptNotFound nf;
XmlPresenterPtr pres;
@@ -134,19 +128,19 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
/// Custom not found handling stage
class CustomNotFoundStage : public DefaultNotFoundStage, public PresentStage {
public:
- CustomNotFoundStage(const ScriptNotFound &, ScriptReaderPtr);
- virtual NextStage run();
- virtual HttpHeaderPtr getHeader() const;
+ CustomNotFoundStage(const ScriptNotFound &, ScriptReaderPtr, CgiRequestContext *);
+ virtual NextStage run(CgiRequestContext *);
+ virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
};
/// The built-in fail-safe unhandled error stage
class DefaultErrorStage : public virtual ResponseStage {
public:
- DefaultErrorStage(const std::exception &);
+ DefaultErrorStage(const std::exception &, CgiRequestContext *);
~DefaultErrorStage();
- virtual NextStage run();
- virtual HttpHeaderPtr getHeader() const;
+ virtual NextStage run(CgiRequestContext *);
+ virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
private:
char * buf;
std::string what;
@@ -156,15 +150,29 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
/// Custom unhandled error handling stage
class CustomErrorStage : public DefaultErrorStage, public PresentStage {
public:
- CustomErrorStage(const std::exception &, ScriptReaderPtr);
- virtual NextStage run();
- virtual HttpHeaderPtr getHeader() const;
+ CustomErrorStage(const std::exception &, ScriptReaderPtr, CgiRequestContext *);
+ virtual NextStage run(CgiRequestContext *);
+ virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
};
+ INITOPTIONS;
+ static boost::intrusive_ptr<HostnamePlatformIdentifier> hpi;
+ static boost::shared_ptr<RouterLoader> router;
+ static SessionContainerPtr sessionsContainer;
+ static std::string sessionCookie;
private:
- SessionPtr cursession;
- std::ostream & IO;
- mutable bool outputCachingActive;
+ static std::string dumpdatadoc;
+ static Glib::ustring errorContentType;
+ static Glib::ustring errorTransformStyle;
+ static std::string defaultPresent;
+ static std::string transformContentType;
+ static std::string transformTargetType;
+ static std::string presentRoot;
+ static std::string requestRoot;
+ static std::string errorPresentRoot;
+ static std::string notFoundPresent;
+ static std::string onErrorPresent;
+ static std::string defaultPresenter;
};
#endif
diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp
deleted file mode 100644
index a4ed8c4..0000000
--- a/project2/cgi/cgiCommon.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <pch.hpp>
-#include "cgiCommon.h"
-#include "optionsSource.h"
-#include "logger.h"
-#include <glibmm/exception.h>
-#include <cgicc/CgiEnvironment.h>
-#include <cgicc/HTTPContentHeader.h>
-#include <cgicc/HTTPStatusHeader.h>
-#include "cgiAppEngine.h"
-#include <boost/bind.hpp>
-#include <cxxabi.h>
-
-// These are templates because some people don't inherit their
-// exceptions from std::exception like normal people (Glib)
-const char *
-what(const Glib::Exception & e)
-{
- return e.what().c_str();
-}
-const char *
-what(const std::exception & e)
-{
- return e.what();
-}
-template <typename E>
-void
-doExceptionReporting(const E & e, std::ostream & IO)
-{
- char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL);
- Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, what(e));
- cgicc::HTTPStatusHeader header(500, e.what());
- header.render(IO);
- IO << "Kaboom!" << std::endl
- << std::endl
- << buf << std::endl
- << "what '" << e.what() << "'" << std::endl;
- free(buf);
-}
-
-void
-cgiServe(cgicc::CgiInput * i, CgiEnvironment * env, std::ostream & IO, const CgiEnvInput * e)
-{
- try {
- cgicc::Cgicc cgi(i);
- env->setCGICC(&cgi, e);
- OptionsSource::loadSources();
- CgiApplicationEngine app(env, IO);
-
- Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
- Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__);
- app.process();
- Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__);
- }
- catch (const std::exception & e) {
- doExceptionReporting(e, IO);
- }
- catch (const Glib::Exception & e) {
- doExceptionReporting(e, IO);
- }
- catch (...) {
- Logger()->messagef(LOG_ERR, "%s: Request errored: Unknown exception", __FUNCTION__);
- cgicc::HTTPStatusHeader header(500, "Unknown exception");
- header.render(IO);
- IO << "Kaboom!" << std::endl
- << std::endl
- << "Unknown exception." << std::endl;
- throw;
- }
-}
-
diff --git a/project2/cgi/cgiCommon.h b/project2/cgi/cgiCommon.h
deleted file mode 100644
index 42a88e6..0000000
--- a/project2/cgi/cgiCommon.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <ostream>
-#include <cgicc/Cgicc.h>
-#include "cgiEnvironment.h"
-
-void cgiServe(cgicc::CgiInput * i, CgiEnvironment *, std::ostream & o, const CgiEnvInput * e);
-
diff --git a/project2/cgi/cgiContentNegotiate.cpp b/project2/cgi/cgiContentNegotiate.cpp
index a7f7557..0b6623e 100644
--- a/project2/cgi/cgiContentNegotiate.cpp
+++ b/project2/cgi/cgiContentNegotiate.cpp
@@ -6,20 +6,20 @@
class ContentNegotiateLoader : public PresenterLoader {
public:
- MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os) const
+ MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os, ExecContext * const & ec) const
{
- auto accept = static_cast<const CgiApplicationEngine *>(CgiApplicationEngine::getCurrent())->env()->getAccept();
+ auto accept = static_cast<const CgiRequestContext *>(ec)->getAccept();
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
BOOST_FOREACH(auto mimetypeAndWeight, tokenizer(accept, boost::char_separator<char>(","))) {
const auto mimetype = mimetypeAndWeight.substr(0, mimetypeAndWeight.find(';'));
if (mimetype == "*/*") break;
BOOST_FOREACH(const auto & t, mappedTypes) {
if (t->Matches(mimetype)) {
- return PresenterLoader::getFor(t->present)->create(s, os);
+ return PresenterLoader::getFor(t->present)->create(s, os, ec);
}
}
}
- return PresenterLoader::getFor((*mappedTypes.begin())->present)->create(s, os);
+ return PresenterLoader::getFor((*mappedTypes.begin())->present)->create(s, os, ec);
}
INITOPTIONS;
diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp
deleted file mode 100644
index d2ecf77..0000000
--- a/project2/cgi/cgiEnvironment.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-#include <pch.hpp>
-#include <boost/bind.hpp>
-#include <boost/foreach.hpp>
-#include <boost/algorithm/string.hpp>
-#include "cgiEnvironment.h"
-#include "appEngine.h"
-#include "exceptions.h"
-#include <map>
-#include <cgicc/Cgicc.h>
-#include <glibmm/regex.h>
-#include <curl/curl.h>
-
-std::string CgiEnvironment::dumpdatadoc;
-Glib::ustring CgiEnvironment::errorContentType;
-Glib::ustring CgiEnvironment::errorTransformStyle;
-std::string CgiEnvironment::defaultPresent;
-std::string CgiEnvironment::transformContentType;
-std::string CgiEnvironment::transformTargetType;
-std::string CgiEnvironment::presentRoot;
-std::string CgiEnvironment::requestRoot;
-std::string CgiEnvironment::errorPresentRoot;
-std::string CgiEnvironment::notFoundPresent;
-std::string CgiEnvironment::onErrorPresent;
-std::string CgiEnvironment::defaultPresenter;
-std::string CgiEnvironment::sessionModule;
-std::string CgiEnvironment::routerType;
-boost::intrusive_ptr<HostnamePlatformIdentifier> CgiEnvironment::hpi;
-
-DECLARE_OPTIONS(CgiEnvironment, "Project2 CGI options")
-("cgi.defaultPresenter", Options::value(&defaultPresenter, "xml"),
- "The default engine for formatting presentations")
-("cgi.transformContentType", Options::value(&transformContentType, "text/xml-xslt"),
- "The content type specified to enable standard internal transformations")
-("cgi.transformTargetType", Options::value(&transformTargetType, "htmldocument"),
- "The transform target type used in standard internal transformations")
-("cgi.defaultPresent", Options::value(&defaultPresent, "index"),
- "The present script to use when no other is specified")
-("cgi.presentRoot", Options::value(&presentRoot, "present"),
- "The folder in which to find presentation scripts")
-("cgi.requestRoot", Options::value(&requestRoot, "request"),
- "The folder in which to find request scripts")
-("cgi.errorPresentRoot", Options::value(&errorPresentRoot, "error"),
- "The folder in which to find presentation scripts for error handling")
-("cgi.errorContentType", Options::value(&errorContentType, "application/xml"),
- "The Content-Type to use in HTTP headers in event of an error")
-("cgi.errorTransformStyle", Options::value(&errorTransformStyle),
- "The xml-stylesheet to specify in the data document in event of an error")
-("cgi.notFoundPresent", Options::value(&notFoundPresent),
- "The present script to use when the requested script does not exist")
-("cgi.onErrorPresent", Options::value(&onErrorPresent),
- "The present script to use when the requested script (or child) fails")
-("cgi.dumpDataDoc", Options::value(&dumpdatadoc),
- "Write a copy of the data document before sending it to the web server")
-("cgi.sessionModule", Options::value(&sessionModule, "xml"),
- "The module with which to implement session management")
-("cgi.hostRegex", (hpi = new HostnamePlatformIdentifier()),
- "Regular expression used to define a hostname -> platform association")
-("cgi.router", Options::value(&routerType, "simple"),
- "Implemenation of router model to map request paths to scripts")
-END_OPTIONS(CgiEnvironment);
-
-CgiEnvironment::CgiEnvironment() :
- cgi(NULL),
- cgienv(NULL)
-{
-}
-
-CgiEnvironment::~CgiEnvironment()
-{
-}
-
-void
-CgiEnvironment::setCGICC(const cgicc::Cgicc * c, const CgiEnvInput * e)
-{
- cgi = c;
- cgienv = e;
- router = boost::bind(&GenLoader<Router, const std::string &>::createNew, boost::cref(routerType), getRedirectURL());
-}
-
-std::string
-CgiEnvironment::getCookieValue(const std::string & name) const
-{
- BOOST_FOREACH(const cgicc::HTTPCookie & c, cgi->getEnvironment().getCookieList()) {
- if (c.getName() == name) {
- return c.getValue();
- }
- }
- throw NoSuchCookie(name);
-}
-
-std::string
-CgiEnvironment::getRequestMethod() const
-{
- return cgi->getEnvironment().getRequestMethod();
-}
-
-std::string
-CgiEnvironment::getRedirectURL() const
-{
- return cgi->getEnvironment().getRedirectURL();
-}
-
-std::string
-CgiEnvironment::getServerName() const
-{
- return cgi->getEnvironment().getServerName();
-}
-
-std::string
-CgiEnvironment::getAccept() const
-{
- return cgi->getEnvironment().getAccept();
-}
-
-const Glib::ustring &
-CgiEnvironment::platform() const
-{
- return hpi->derivedPlatform();
-}
-
-CgiEnvironment::ETags
-CgiEnvironment::getRequestETags() const
-{
- const std::string e = cgienv->getenv("HTTP_IF_NONE_MATCH");
- ETags etags;
- boost::split(etags, e, boost::is_any_of(" ,"), boost::algorithm::token_compress_on);
- return etags;
-}
-
-time_t
-CgiEnvironment::getRequestModifiedSince() const
-{
- return curl_getdate(cgienv->getenv("HTTP_IF_MODIFIED_SINCE").c_str(), NULL);
-}
-
-Glib::ustring
-CgiEnvironment::getParamUri(VariableType p) const
-{
- return router->routeParameter(p);
-}
-
-unsigned int
-CgiEnvironment::getParamUriCount() const
-{
- return router->parameterCount();
-}
-
-void
-CgiEnvironment::applyAllParameters(const boost::function<void (const std::string &, const std::string &)> & func) const
-{
- BOOST_FOREACH(const auto & f, cgi->getElements()) {
- func(f.getName(), f.getValue());
- }
-}
-
-Glib::ustring
-CgiEnvironment::getParamQuery(const std::string & p) const
-{
- cgicc::const_form_iterator i = cgi->getElement(p);
- if (i == cgi->getElements().end()) {
- throw ParamNotFound(p);
- }
- return (*cgi)(p);
-}
-
-HostnamePlatformIdentifier::HostnamePlatformIdentifier() :
- platform(NULL)
-{
-}
-
-HostnamePlatformIdentifier::~HostnamePlatformIdentifier()
-{
- reset();
-}
-
-const Glib::ustring &
-HostnamePlatformIdentifier::derivedPlatform() const
-{
- if (platform) {
- return *platform;
- }
- throw NoSuchPlatform(Environment::getCurrent()->getServerName());
-}
-
-void
-HostnamePlatformIdentifier::reset() const
-{
- if (platform) {
- delete platform;
- platform = NULL;
- }
-}
-
-bool
-HostnamePlatformIdentifier::paramRequired() const
-{
- return true;
-}
-
-void
-HostnamePlatformIdentifier::consume(const Glib::ustring & p, const VariableType & r) const
-{
- if (!platform && Glib::Regex::create(r, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL)->match(Environment::getCurrent()->getServerName())) {
- platform = new Glib::ustring(p);
- }
-}
-
diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h
deleted file mode 100644
index e9de59d..0000000
--- a/project2/cgi/cgiEnvironment.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef ENVPROC_H
-#define ENVPROC_H
-
-#include <string>
-#include <vector>
-#include "environment.h"
-#include "cgiEnvInput.h"
-#include "cgiRouter.h"
-#include <cgicc/CgiEnvironment.h>
-#include <lazyPointer.h>
-
-SimpleMessageException(NoSuchCookie);
-
-namespace cgicc {
- class Cgicc;
-}
-
-class HostnamePlatformIdentifier : public Options::Target {
- public:
- HostnamePlatformIdentifier();
- virtual ~HostnamePlatformIdentifier();
- void reset() const;
- bool paramRequired() const;
- void consume(const Glib::ustring &, const VariableType &) const;
- const Glib::ustring & derivedPlatform() const;
- private:
- mutable Glib::ustring * platform;
-};
-
-class CgiEnvironment : public Environment {
- public:
- typedef std::string ETag;
- typedef std::vector<ETag> ETags;
-
- CgiEnvironment();
- virtual ~CgiEnvironment();
-
- Glib::ustring getParamUri(VariableType idx) const;
- unsigned int getParamUriCount() const;
- Glib::ustring getParamQuery(const std::string & idx) const;
- void applyAllParameters(const boost::function<void (const std::string &, const std::string &)> &) const;
- std::string getServerName() const;
- std::string getRedirectURL() const;
- std::string getRequestMethod() const;
- std::string getAccept() const;
- ETags getRequestETags() const;
- time_t getRequestModifiedSince() const;
- std::string getCookieValue(const std::string & name) const;
-
- void setCGICC(const cgicc::Cgicc *, const CgiEnvInput * cgienv);
- const cgicc::Cgicc * cgi;
- const CgiEnvInput * cgienv;
-
- private:
- const Glib::ustring & platform() const;
-
- public:
- INITOPTIONS;
- static boost::intrusive_ptr<HostnamePlatformIdentifier> hpi;
- static std::string dumpdatadoc;
- static Glib::ustring errorContentType;
- static Glib::ustring errorTransformStyle;
- static std::string defaultPresent;
- static std::string transformContentType;
- static std::string transformTargetType;
- static std::string presentRoot;
- static std::string requestRoot;
- static std::string errorPresentRoot;
- static std::string notFoundPresent;
- static std::string onErrorPresent;
- static std::string defaultPresenter;
- static std::string sessionModule;
- static std::string routerType;
- typedef LazyPointer<const Router> RouterPtr;
- RouterPtr router;
-};
-
-#endif
diff --git a/project2/cgi/cgiProgRouter.cpp b/project2/cgi/cgiProgRouter.cpp
index e8ae15d..8fce50d 100644
--- a/project2/cgi/cgiProgRouter.cpp
+++ b/project2/cgi/cgiProgRouter.cpp
@@ -1,7 +1,10 @@
#include <pch.hpp>
#include <boost/foreach.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string/predicate.hpp>
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
+#include "commonObjects.h"
+#include "rowProcessor.h"
#include "presenter.h"
#include "safeMapFind.h"
#include "scriptStorage.h"
@@ -82,8 +85,8 @@ class RoutingTable {
public:
Route(ScriptNodePtr s) :
SourceObject(s),
- present(s->value("present").as<std::string>()),
- path(s->value("path").as<std::string>())
+ present(s->value("present", NULL).as<std::string>()),
+ path(s->value("path", NULL).as<std::string>())
{
boost::filesystem::path fspath = path;
boost::filesystem::path::iterator p = fspath.begin();
@@ -204,14 +207,14 @@ class Routes : public RowSet {
mutable Columns columns;
friend class Routes;
};
- void execute(const Glib::ustring & filter, const RowProcessor * rp) const
+ void execute(const Glib::ustring & filter, const RowProcessorCallback & rp, ExecContext *) const
{
RouteRowState rs;
BOOST_FOREACH(const auto & r, ProgRouterLoader::routingTable.routes) {
if (boost::algorithm::starts_with(r->path, filter)) {
rs.fields[0] = VariableType(r->present);
rs.fields[1] = VariableType(r->path);
- rs.process(rp);
+ rp(&rs);
}
}
}
diff --git a/project2/cgi/cgiRequestContext.cpp b/project2/cgi/cgiRequestContext.cpp
new file mode 100644
index 0000000..5a93243
--- /dev/null
+++ b/project2/cgi/cgiRequestContext.cpp
@@ -0,0 +1,161 @@
+#include <pch.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+#include "cgiRequestContext.h"
+#include "cgiAppEngine.h"
+#include "exceptions.h"
+#include <map>
+#include <cgicc/Cgicc.h>
+#include <glibmm/regex.h>
+#include <curl/curl.h>
+#include <boost/uuid/uuid_io.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+CgiRequestContext::CgiRequestContext(cgicc::CgiInput * i, const CgiEnvInput & e) :
+ cgi(i),
+ router(boost::bind(&RouterLoader::create, boost::cref(CgiApplicationEngine::router), getRedirectURL())),
+ cgienv(e),
+ session(boost::bind(&CgiRequestContext::getSessionInternal, this))
+{
+}
+
+CgiRequestContext::~CgiRequestContext()
+{
+}
+
+SessionPtr
+CgiRequestContext::getSession() const
+{
+ return session;
+}
+
+SessionPtr
+CgiRequestContext::getSessionInternal() const
+{
+ try {
+ return CgiApplicationEngine::sessionsContainer->GetSession(boost::uuids::string_generator()(getCookieValue(CgiApplicationEngine::sessionCookie)));
+ }
+ catch (const NoSuchCookie &) {
+ return CgiApplicationEngine::sessionsContainer->GetSession(boost::uuids::uuid());
+ }
+}
+
+std::string
+CgiRequestContext::getCookieValue(const std::string & name) const
+{
+ BOOST_FOREACH(const cgicc::HTTPCookie & c, cgi.getEnvironment().getCookieList()) {
+ if (c.getName() == name) {
+ return c.getValue();
+ }
+ }
+ throw NoSuchCookie(name);
+}
+
+std::string
+CgiRequestContext::getRequestMethod() const
+{
+ return cgi.getEnvironment().getRequestMethod();
+}
+
+std::string
+CgiRequestContext::getRedirectURL() const
+{
+ return cgi.getEnvironment().getRedirectURL();
+}
+
+std::string
+CgiRequestContext::getServerName() const
+{
+ return cgi.getEnvironment().getServerName();
+}
+
+std::string
+CgiRequestContext::getAccept() const
+{
+ return cgi.getEnvironment().getAccept();
+}
+
+CgiRequestContext::ETags
+CgiRequestContext::getRequestETags() const
+{
+ const std::string e = cgienv.getenv("HTTP_IF_NONE_MATCH");
+ ETags etags;
+ boost::split(etags, e, boost::is_any_of(" ,"), boost::algorithm::token_compress_on);
+ return etags;
+}
+
+time_t
+CgiRequestContext::getRequestModifiedSince() const
+{
+ return curl_getdate(cgienv.getenv("HTTP_IF_MODIFIED_SINCE").c_str(), NULL);
+}
+
+Glib::ustring
+CgiRequestContext::getParamUri(VariableType p) const
+{
+ return router->routeParameter(p);
+}
+
+unsigned int
+CgiRequestContext::getParamUriCount() const
+{
+ return router->parameterCount();
+}
+
+void
+CgiRequestContext::applyAllParameters(const boost::function<void (const std::string &, const std::string &)> & func) const
+{
+ BOOST_FOREACH(const auto & f, cgi.getElements()) {
+ func(f.getName(), f.getValue());
+ }
+}
+
+VariableType
+CgiRequestContext::getParameter(const VariableType & p) const
+{
+ cgicc::const_form_iterator i = cgi.getElement(p);
+ if (i == cgi.getElements().end()) {
+ throw ParamNotFound(p);
+ }
+ return cgi(p);
+}
+
+HostnamePlatformIdentifier::HostnamePlatformIdentifier()
+{
+}
+
+HostnamePlatformIdentifier::~HostnamePlatformIdentifier()
+{
+}
+
+const Glib::ustring &
+HostnamePlatformIdentifier::derivedPlatform(CgiRequestContext * crc) const
+{
+ auto pi = std::find_if(platHosts.begin(), platHosts.end(), [crc](const PlatformHostname & r) -> bool {
+ return r.second->match(crc->getServerName());
+ });
+ if (pi == platHosts.end()) {
+ throw NoSuchPlatform(crc->getServerName());
+ }
+ return pi->first;
+}
+
+void
+HostnamePlatformIdentifier::reset() const
+{
+ platHosts.clear();
+}
+
+bool
+HostnamePlatformIdentifier::paramRequired() const
+{
+ return true;
+}
+
+void
+HostnamePlatformIdentifier::consume(const Glib::ustring & p, const VariableType & r, const Options::CurrentPlatform &) const
+{
+ platHosts.push_back(PlatformHostname(p, Glib::Regex::create(r, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL)));
+}
+
diff --git a/project2/cgi/cgiRequestContext.h b/project2/cgi/cgiRequestContext.h
new file mode 100644
index 0000000..1dbc613
--- /dev/null
+++ b/project2/cgi/cgiRequestContext.h
@@ -0,0 +1,68 @@
+#ifndef ENVPROC_H
+#define ENVPROC_H
+
+#include <string>
+#include <vector>
+#include "cgiEnvInput.h"
+#include "cgiRouter.h"
+#include "execContext.h"
+#include <cgicc/CgiEnvironment.h>
+#include <cgicc/Cgicc.h>
+#include <lazyPointer.h>
+#include <glibmm/refptr.h>
+
+SimpleMessageException(NoSuchCookie);
+
+class CgiRequestContext;
+namespace Glib {
+ class Regex;
+}
+
+class HostnamePlatformIdentifier : public Options::Target {
+ public:
+ HostnamePlatformIdentifier();
+ virtual ~HostnamePlatformIdentifier();
+ void reset() const;
+ bool paramRequired() const;
+ void consume(const Glib::ustring &, const VariableType &, const Options::CurrentPlatform &) const;
+ const Glib::ustring & derivedPlatform(CgiRequestContext *) const;
+ private:
+ typedef std::pair<Glib::ustring, Glib::RefPtr<Glib::Regex>> PlatformHostname;
+ typedef std::vector<PlatformHostname> PlatformHostnameList;
+ mutable PlatformHostnameList platHosts;
+};
+
+class CgiRequestContext : public ExecContext {
+ public:
+ typedef std::string ETag;
+ typedef std::vector<ETag> ETags;
+
+ CgiRequestContext(cgicc::CgiInput *, const CgiEnvInput & cgienv);
+ virtual ~CgiRequestContext();
+
+ const cgicc::Cgicc cgi;
+
+ Glib::ustring getParamUri(VariableType idx) const;
+ unsigned int getParamUriCount() const;
+ VariableType getParameter(const VariableType & idx) const;
+ void applyAllParameters(const boost::function<void (const std::string &, const std::string &)> &) const;
+ SessionPtr getSession() const;
+ std::string getServerName() const;
+ std::string getRedirectURL() const;
+ std::string getRequestMethod() const;
+ std::string getAccept() const;
+ ETags getRequestETags() const;
+ time_t getRequestModifiedSince() const;
+ std::string getCookieValue(const std::string & name) const;
+ LazyPointer<Router> router;
+
+ boost::posix_time::ptime startTime;
+ boost::posix_time::ptime endTime;
+
+ private:
+ const CgiEnvInput & cgienv;
+ LazyPointer<Session> session;
+ SessionPtr getSessionInternal() const;
+};
+
+#endif
diff --git a/project2/cgi/cgiRequestID.cpp b/project2/cgi/cgiRequestID.cpp
index da8ad6a..60baa1e 100644
--- a/project2/cgi/cgiRequestID.cpp
+++ b/project2/cgi/cgiRequestID.cpp
@@ -1,9 +1,8 @@
#include <pch.hpp>
#include <variables.h>
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include <scriptLoader.h>
#include <scriptStorage.h>
-#include <appEngine.h>
#include <gcrypt.h>
#include <scopeObject.h>
#include <iomanip>
@@ -16,16 +15,16 @@ class CgiRequestID : public VariableImplDyn {
{
}
- VariableType value() const
+ VariableType value(ExecContext * ec) const
{
gcry_md_hd_t state;
gcry_md_open(&state, GCRY_MD_SHA1, 0);
ScopeObject gcryClose([&state] { gcry_md_close(state); });
- auto _env = static_cast<const CgiEnvironment *>(ApplicationEngine::getCurrent()->env());
- gcryApplyString(state, _env->getRedirectURL());
+ auto crc = static_cast<const CgiRequestContext *>(ec);
+ gcryApplyString(state, crc->getRedirectURL());
- _env->applyAllParameters([&state,this](const std::string & name, const std::string & value) {
+ crc->applyAllParameters([&state, this](const std::string & name, const std::string & value) {
gcryApplyString(state, name);
gcryApplyString(state, value);
});
diff --git a/project2/cgi/cgiResultStatic.cpp b/project2/cgi/cgiResultStatic.cpp
index b5fecd7..ab4ff43 100644
--- a/project2/cgi/cgiResultStatic.cpp
+++ b/project2/cgi/cgiResultStatic.cpp
@@ -4,7 +4,7 @@
class StaticToCgiResult : public TransformImpl<StaticContent, CgiResult> {
public:
- void transform(const StaticContent * sc, CgiResult * cr) const {
+ void transform(const StaticContent * sc, CgiResult * cr, ExecContext *) const {
cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", sc->getContentType(), sc->getEncoding()));
cr->header->addHeader("Content-Length", Glib::ustring::compose("%1", sc->getSizeInBytes()));
char buf[100];
diff --git a/project2/cgi/cgiResultWritable.cpp b/project2/cgi/cgiResultWritable.cpp
index ea17d3b..357a57c 100644
--- a/project2/cgi/cgiResultWritable.cpp
+++ b/project2/cgi/cgiResultWritable.cpp
@@ -3,11 +3,11 @@
class WritableToCgiResult : public TransformImpl<WritableContent, CgiResult> {
public:
- void transform(const WritableContent * wc, CgiResult * cr) const {
+ void transform(const WritableContent * wc, CgiResult * cr, ExecContext * ec) const {
cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", wc->getContentType(), cr->encoding));
cr->header->addHeader("Cache-control", "no-cache");
cr->header->render(cr->stream);
- wc->writeTo(cr->stream, cr->encoding);
+ wc->writeTo(cr->stream, cr->encoding, ec);
}
};
DECLARE_TRANSFORM(WritableToCgiResult);
diff --git a/project2/cgi/cgiRouter.h b/project2/cgi/cgiRouter.h
index dd9c0e6..4a88b19 100644
--- a/project2/cgi/cgiRouter.h
+++ b/project2/cgi/cgiRouter.h
@@ -14,6 +14,7 @@ class Router : public IntrusivePtrBase {
virtual unsigned int parameterCount() const = 0;
virtual void present(const MultiRowSetPresenter * p) const = 0;
};
+typedef boost::intrusive_ptr<Router> RouterPtr;
typedef GenLoader<Router, const std::string &> RouterLoader;
#endif
diff --git a/project2/cgi/cgiSimpleRouter.cpp b/project2/cgi/cgiSimpleRouter.cpp
index cd14c53..b67848e 100644
--- a/project2/cgi/cgiSimpleRouter.cpp
+++ b/project2/cgi/cgiSimpleRouter.cpp
@@ -1,4 +1,4 @@
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include <boost/filesystem/path.hpp>
#include "scriptLoader.h"
#include "presenter.h"
diff --git a/project2/cgi/cgiStageCacheHit.cpp b/project2/cgi/cgiStageCacheHit.cpp
index d398e8f..d74c02f 100644
--- a/project2/cgi/cgiStageCacheHit.cpp
+++ b/project2/cgi/cgiStageCacheHit.cpp
@@ -1,6 +1,6 @@
#include <pch.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
@@ -12,13 +12,13 @@ CgiApplicationEngine::CacheHitStage::CacheHitStage(ScriptNodePtr s, PresenterCac
}
CgiApplicationEngine::NextStage
-CgiApplicationEngine::CacheHitStage::run()
+CgiApplicationEngine::CacheHitStage::run(CgiRequestContext *)
{
return NextStage(NULL, this, pc, NULL);
}
CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::CacheHitStage::getHeader() const
+CgiApplicationEngine::CacheHitStage::getHeader(CgiRequestContext *) const
{
return HttpHeaderPtr(new Project2HttpHeader("200 OK"));
}
diff --git a/project2/cgi/cgiStageCustomError.cpp b/project2/cgi/cgiStageCustomError.cpp
index 56739fd..e38c7ec 100644
--- a/project2/cgi/cgiStageCustomError.cpp
+++ b/project2/cgi/cgiStageCustomError.cpp
@@ -1,28 +1,28 @@
#include <pch.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
#include "logger.h"
-CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const std::exception & ex, ScriptReaderPtr s) :
+CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const std::exception & ex, ScriptReaderPtr s, CgiRequestContext * crc) :
CgiApplicationEngine::ResponseStage(s->root()),
::CommonObjects(s->root()),
::CheckHost(s->root()),
- CgiApplicationEngine::DefaultErrorStage(ex),
- CgiApplicationEngine::PresentStage(s)
+ CgiApplicationEngine::DefaultErrorStage(ex, crc),
+ CgiApplicationEngine::PresentStage(s, crc)
{
}
CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::CustomErrorStage::getHeader() const
+CgiApplicationEngine::CustomErrorStage::getHeader(CgiRequestContext * ec) const
{
- return CgiApplicationEngine::DefaultErrorStage::getHeader();
+ return CgiApplicationEngine::DefaultErrorStage::getHeader(ec);
}
CgiApplicationEngine::NextStage
-CgiApplicationEngine::CustomErrorStage::run()
+CgiApplicationEngine::CustomErrorStage::run(CgiRequestContext * crc)
{
- CgiApplicationEngine::DefaultErrorStage::run();
- return CgiApplicationEngine::PresentStage::run();
+ CgiApplicationEngine::DefaultErrorStage::run(crc);
+ return CgiApplicationEngine::PresentStage::run(crc);
}
diff --git a/project2/cgi/cgiStageCustomNotFound.cpp b/project2/cgi/cgiStageCustomNotFound.cpp
index 872da77..48fbf64 100644
--- a/project2/cgi/cgiStageCustomNotFound.cpp
+++ b/project2/cgi/cgiStageCustomNotFound.cpp
@@ -1,28 +1,28 @@
#include <pch.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
#include "logger.h"
-CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const ScriptNotFound & notfound, ScriptReaderPtr s) :
+CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const ScriptNotFound & notfound, ScriptReaderPtr s, CgiRequestContext * crc) :
CgiApplicationEngine::ResponseStage(s->root()),
::CommonObjects(s->root()),
::CheckHost(s->root()),
CgiApplicationEngine::DefaultNotFoundStage(notfound),
- CgiApplicationEngine::PresentStage(s)
+ CgiApplicationEngine::PresentStage(s, crc)
{
}
CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::CustomNotFoundStage::getHeader() const
+CgiApplicationEngine::CustomNotFoundStage::getHeader(CgiRequestContext * crc) const
{
- return CgiApplicationEngine::DefaultNotFoundStage::getHeader();
+ return CgiApplicationEngine::DefaultNotFoundStage::getHeader(crc);
}
CgiApplicationEngine::NextStage
-CgiApplicationEngine::CustomNotFoundStage::run()
+CgiApplicationEngine::CustomNotFoundStage::run(CgiRequestContext * crc)
{
- CgiApplicationEngine::DefaultNotFoundStage::run();
- return CgiApplicationEngine::PresentStage::run();
+ CgiApplicationEngine::DefaultNotFoundStage::run(crc);
+ return CgiApplicationEngine::PresentStage::run(crc);
}
diff --git a/project2/cgi/cgiStageDefaultError.cpp b/project2/cgi/cgiStageDefaultError.cpp
index 4c3eefe..d230a21 100644
--- a/project2/cgi/cgiStageDefaultError.cpp
+++ b/project2/cgi/cgiStageDefaultError.cpp
@@ -2,22 +2,22 @@
#include "cgiAppEngine.h"
#include "cgiHttpHeader.h"
#include "logger.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include <cxxabi.h>
static const Glib::ustring DefaultErrorStageResp("error");
-CgiApplicationEngine::DefaultErrorStage::DefaultErrorStage(const std::exception & ex) :
+CgiApplicationEngine::DefaultErrorStage::DefaultErrorStage(const std::exception & ex, CgiRequestContext * crc) :
CgiApplicationEngine::ResponseStage(NULL),
buf(__cxxabiv1::__cxa_demangle(typeid(ex).name(), NULL, NULL, NULL)),
what(ex.what()),
- pres(new XmlPresenter(DefaultErrorStageResp, env()->errorTransformStyle, env()->errorContentType))
+ pres(new XmlPresenter(DefaultErrorStageResp, CgiApplicationEngine::errorTransformStyle, CgiApplicationEngine::errorContentType))
{
auto xp = dynamic_cast<TransformSource *>(pres.get());
auto cp = dynamic_cast<ContentPresenter *>(pres.get());
- if (xp && cp && cp->contentType == this->env()->transformContentType) {
- auto h = TransformTargetLoader::getFor(this->env()->transformTargetType)->create(root, Default);
- xp->addTarget(h, root);
+ if (xp && cp && cp->contentType == CgiApplicationEngine::transformContentType) {
+ auto h = TransformTargetLoader::getFor(CgiApplicationEngine::transformTargetType)->create(root, Default);
+ xp->addTarget(h, crc, root);
}
}
@@ -27,15 +27,15 @@ CgiApplicationEngine::DefaultErrorStage::~DefaultErrorStage()
}
CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::DefaultErrorStage::getHeader() const
+CgiApplicationEngine::DefaultErrorStage::getHeader(CgiRequestContext *) const
{
return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error"));
}
CgiApplicationEngine::NextStage
-CgiApplicationEngine::DefaultErrorStage::run()
+CgiApplicationEngine::DefaultErrorStage::run(CgiRequestContext * crc)
{
- pres->init();
+ pres->init(crc);
pres->addNamedValue("error-type", Scripts::scriptNamespacePrefix, buf);
pres->addNamedValue("error-what", Scripts::scriptNamespacePrefix, what.c_str());
return NextStage(NULL, this, pres.get(), pres.get());
diff --git a/project2/cgi/cgiStageDefaultNotFound.cpp b/project2/cgi/cgiStageDefaultNotFound.cpp
index e497058..bfb737f 100644
--- a/project2/cgi/cgiStageDefaultNotFound.cpp
+++ b/project2/cgi/cgiStageDefaultNotFound.cpp
@@ -1,6 +1,6 @@
#include <pch.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
#include "logger.h"
@@ -9,21 +9,21 @@ static const Glib::ustring DefaultNotFoundStageResp("notfound");
CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const ScriptNotFound & notfound) :
CgiApplicationEngine::ResponseStage(NULL),
nf(notfound),
- pres(new XmlPresenter(DefaultNotFoundStageResp, env()->errorTransformStyle, env()->errorContentType))
+ pres(new XmlPresenter(DefaultNotFoundStageResp, CgiApplicationEngine::errorTransformStyle, CgiApplicationEngine::errorContentType))
{
Logger()->messagef(LOG_ERR, "%s: Resource not found: %s", __FUNCTION__, nf.what());
}
CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::DefaultNotFoundStage::getHeader() const
+CgiApplicationEngine::DefaultNotFoundStage::getHeader(CgiRequestContext *) const
{
return HttpHeaderPtr(new Project2HttpHeader("404 Not found"));
}
CgiApplicationEngine::NextStage
-CgiApplicationEngine::DefaultNotFoundStage::run()
+CgiApplicationEngine::DefaultNotFoundStage::run(CgiRequestContext * crc)
{
- pres->init();
+ pres->init(crc);
pres->addNamedValue("missing-resource", Scripts::scriptNamespacePrefix, nf.what());
return NextStage(NULL, this, pres.get(), pres.get());
}
diff --git a/project2/cgi/cgiStageFail.cpp b/project2/cgi/cgiStageFail.cpp
index 019ab8e..461c8a7 100644
--- a/project2/cgi/cgiStageFail.cpp
+++ b/project2/cgi/cgiStageFail.cpp
@@ -1,7 +1,7 @@
#include <pch.hpp>
#include <boost/lexical_cast.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
#include "logger.h"
@@ -14,13 +14,13 @@ namespace CgiApplicationExtras {
message(m) {
}
- CgiApplicationEngine::HttpHeaderPtr getHeader() const
+ CgiApplicationEngine::HttpHeaderPtr getHeader(CgiRequestContext *) const
{
Project2HttpHeader * header = new Project2HttpHeader(boost::lexical_cast<std::string>(code) + " " + message);
return CgiApplicationEngine::HttpHeaderPtr(header);
}
- CgiApplicationEngine::NextStage run()
+ CgiApplicationEngine::NextStage run(CgiRequestContext *)
{
return CgiApplicationEngine::NextStage(NULL, this, NULL, NULL);
}
@@ -37,9 +37,9 @@ namespace CgiApplicationExtras {
code(e, "code", 500),
message(e, "message", "Application error") {
}
- void execute(const MultiRowSetPresenter *) const {
+ void execute(const MultiRowSetPresenter *, ExecContext * ec) const {
throw CgiApplicationEngine::ResponseStagePtr(
- new FailStage(code(), message()));
+ new FailStage(code(ec), message(ec)));
}
private:
Variable code, message;
diff --git a/project2/cgi/cgiStageInitial.cpp b/project2/cgi/cgiStageInitial.cpp
index d5fe424..1326af8 100644
--- a/project2/cgi/cgiStageInitial.cpp
+++ b/project2/cgi/cgiStageInitial.cpp
@@ -1,17 +1,18 @@
#include <pch.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "exceptions.h"
CgiApplicationEngine::NextStage
-CgiApplicationEngine::InitialStage::run()
+CgiApplicationEngine::InitialStage::run(CgiRequestContext * crc)
{
- const CgiEnvironment * e = env();
- if (e->getRequestMethod() == "POST") {
- return NextStage(new RequestStage(ScriptReader::resolveScript(e->requestRoot, e->router->route(), false)));
+ if (crc->getRequestMethod() == "POST") {
+ return NextStage(new RequestStage(ScriptReader::resolveScript(CgiApplicationEngine::requestRoot,
+ crc->router->route(), false)));
}
else {
- return NextStage(new PresentStage(ScriptReader::resolveScript(e->presentRoot, e->router->isDefault() ? e->defaultPresent : e->router->route(), false)));
+ return NextStage(new PresentStage(ScriptReader::resolveScript(CgiApplicationEngine::presentRoot,
+ crc->router->isDefault() ? CgiApplicationEngine::defaultPresent : crc->router->route(), false), crc));
}
}
diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp
index 90299fe..f077111 100644
--- a/project2/cgi/cgiStagePresent.cpp
+++ b/project2/cgi/cgiStagePresent.cpp
@@ -1,41 +1,41 @@
#include <pch.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
#include "safeMapFind.h"
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
-CgiApplicationEngine::PresentStage::PresentStage(ScriptReaderPtr s) :
+CgiApplicationEngine::PresentStage::PresentStage(ScriptReaderPtr s, CgiRequestContext * crc) :
CgiApplicationEngine::ResponseStage(s->root()),
CommonObjects(s->root()),
CheckHost(s->root()),
ViewHost(s->root()),
- presenter([this] {
- auto p = PresenterLoader::getFor(this->env()->defaultPresenter)->create(root, Default);
+ presenter([this, crc] {
+ auto p = PresenterLoader::getFor(CgiApplicationEngine::defaultPresenter)->create(root, Default, crc);
auto xp = dynamic_cast<TransformSource *>(p);
auto cp = dynamic_cast<ContentPresenter *>(p);
- if (xp && cp && cp->contentType == this->env()->transformContentType) {
- auto h = TransformTargetLoader::getFor(this->env()->transformTargetType)->create(root, Default);
- xp->addTarget(h, root);
+ if (xp && cp && cp->contentType == CgiApplicationEngine::transformContentType) {
+ auto h = TransformTargetLoader::getFor(CgiApplicationEngine::transformTargetType)->create(root, Default);
+ xp->addTarget(h, crc, root);
}
return p;
})
{
s->loader.addLoadTarget(s->root(), Storer::into<OutputOptionsLoader>(&outputOptions));
- s->loader.addLoadTarget(s->root(), Storer::into<PresenterLoader>(&presenter, Scripted));
+ s->loader.addLoadTarget(s->root(), Storer::into<PresenterLoader>(&presenter, Scripted, crc));
s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(&caches));
}
CgiApplicationEngine::NextStage
-CgiApplicationEngine::PresentStage::run()
+CgiApplicationEngine::PresentStage::run(CgiRequestContext * crc)
{
- runChecks();
+ runChecks(crc);
PresenterCaches backFill;
- time_t reqMS = this->env()->getRequestModifiedSince();
- CgiEnvironment::ETags etags = this->env()->getRequestETags();
+ time_t reqMS = crc->getRequestModifiedSince();
+ CgiRequestContext::ETags etags = crc->getRequestETags();
BOOST_FOREACH(const PresenterCachePtr & pc, caches) {
- if (pc->check(root->script->modifiedTime())) {
+ if (pc->check(root->script->modifiedTime(), crc)) {
if (reqMS >= pc->getModifiedTime() && (etags.empty() || containerContains(etags, pc->getSHA1()))) {
header = HttpHeaderPtr(new Project2HttpHeader("304 Not Modified"));
return NextStage(NULL, this, NULL, NULL);
@@ -49,7 +49,7 @@ CgiApplicationEngine::PresentStage::run()
}
}
try {
- executeViews();
+ executeViews(crc);
header = HttpHeaderPtr(new Project2HttpHeader("200 OK"));
return NextStage(NULL, this, boost::dynamic_pointer_cast<TransformSource>(presenter), presenter);
}
@@ -66,7 +66,7 @@ CgiApplicationEngine::PresentStage::run()
}
MultiRowSetPresenterPtr
-CgiApplicationEngine::PresentStage::getPresenter() const
+CgiApplicationEngine::PresentStage::getPresenter(ExecContext *) const
{
return presenter;
}
@@ -77,7 +77,7 @@ CgiApplicationEngine::ResponseStage::ResponseStage(ScriptNodePtr r) :
}
CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::PresentStage::getHeader() const
+CgiApplicationEngine::PresentStage::getHeader(CgiRequestContext *) const
{
return header;
}
diff --git a/project2/cgi/cgiStageRedirect.cpp b/project2/cgi/cgiStageRedirect.cpp
index 4a4cd02..d6fee08 100644
--- a/project2/cgi/cgiStageRedirect.cpp
+++ b/project2/cgi/cgiStageRedirect.cpp
@@ -1,6 +1,6 @@
#include <pch.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
#include "logger.h"
@@ -12,14 +12,14 @@ namespace CgiApplicationExtras {
url(u) {
}
- CgiApplicationEngine::HttpHeaderPtr getHeader() const
+ CgiApplicationEngine::HttpHeaderPtr getHeader(CgiRequestContext *) const
{
Project2HttpHeader * header = new Project2HttpHeader("301 Moved Permanently");
header->addHeader("Location", url);
return CgiApplicationEngine::HttpHeaderPtr(header);
}
- CgiApplicationEngine::NextStage run()
+ CgiApplicationEngine::NextStage run(CgiRequestContext *)
{
return CgiApplicationEngine::NextStage(NULL, this, NULL, NULL);
}
@@ -34,8 +34,8 @@ namespace CgiApplicationExtras {
View(e),
url(e, "url") {
}
- void execute(const MultiRowSetPresenter *) const {
- throw CgiApplicationEngine::ResponseStagePtr(new RedirectStage(url()));
+ void execute(const MultiRowSetPresenter *, ExecContext * ec) const {
+ throw CgiApplicationEngine::ResponseStagePtr(new RedirectStage(url(ec)));
}
private:
Variable url;
diff --git a/project2/cgi/cgiStageRequest.cpp b/project2/cgi/cgiStageRequest.cpp
index 37faaae..78d933b 100644
--- a/project2/cgi/cgiStageRequest.cpp
+++ b/project2/cgi/cgiStageRequest.cpp
@@ -1,6 +1,6 @@
#include <pch.hpp>
#include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
#include "scriptLoader.h"
#include <boost/foreach.hpp>
@@ -17,26 +17,26 @@ CgiApplicationEngine::RequestStage::RequestStage(ScriptReaderPtr s) :
}
CgiApplicationEngine::NextStage
-CgiApplicationEngine::RequestStage::run()
+CgiApplicationEngine::RequestStage::run(CgiRequestContext * ec)
{
- runChecks();
- execute();
- if (!present().isNull()) {
- return NextStage(new PresentStage(ScriptReader::resolveScript(env()->presentRoot, present(), false)), this);
+ runChecks(ec);
+ execute(ec);
+ if (!present(ec).isNull()) {
+ return NextStage(new PresentStage(ScriptReader::resolveScript(CgiApplicationEngine::presentRoot, present(ec), false), ec), this);
}
return NextStage(NULL, this);
}
CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::RequestStage::getHeader() const
+CgiApplicationEngine::RequestStage::getHeader(CgiRequestContext * ec) const
{
Project2HttpHeader * header;
- if (redirect().isNull()) {
+ if (redirect(ec).isNull()) {
header = new Project2HttpHeader("200 OK");
}
else {
header = new Project2HttpHeader("301 Moved Permanently");
- header->addHeader("Location", redirect());
+ header->addHeader("Location", redirect(ec));
}
header->addHeader("Cache-control", "no-cache");
return HttpHeaderPtr(header);
diff --git a/project2/cgi/cgiUriParam.cpp b/project2/cgi/cgiUriParam.cpp
index c65119e..985048d 100644
--- a/project2/cgi/cgiUriParam.cpp
+++ b/project2/cgi/cgiUriParam.cpp
@@ -1,9 +1,8 @@
#include <pch.hpp>
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include <variables.h>
#include <scriptLoader.h>
#include <scriptStorage.h>
-#include <appEngine.h>
/// Variable implementation to access URI path fragments
class VariableUri : public VariableImplDyn {
@@ -13,16 +12,16 @@ class VariableUri : public VariableImplDyn {
index(e, "index")
{
}
- VariableType value() const
+ VariableType value(ExecContext * ec) const
{
try {
- return static_cast<const CgiEnvironment *>(ApplicationEngine::getCurrent()->env())->getParamUri(index());
+ return static_cast<const CgiRequestContext *>(ec)->getParamUri(index(ec));
}
catch (...) {
if (!defaultValue) {
throw;
}
- return (*defaultValue)();
+ return (*defaultValue)(ec);
}
}
private:
diff --git a/project2/cgi/p2webCgi.cpp b/project2/cgi/p2webCgi.cpp
index 1b2aa99..4f806b2 100644
--- a/project2/cgi/p2webCgi.cpp
+++ b/project2/cgi/p2webCgi.cpp
@@ -1,5 +1,5 @@
-#include "cgiCommon.h"
-#include "scriptLoader.h"
+#include "cgiAppEngine.h"
+#include "optionsSource.h"
#include <boost/bind.hpp>
class GetEnv : public CgiEnvInput {
@@ -16,9 +16,12 @@ int
main(void)
{
Plugable::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1));
- CgiEnvironment env;
+ CgiApplicationEngine app;
GetEnv ge;
- cgiServe(NULL, &env, std::cout, &ge);
+ CgiRequestContext crc(NULL, ge);
+ OptionsSource::loadSources(boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc));
+ Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
+ app.process(std::cout, &crc);
Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1));
Plugable::onAllComponents(boost::bind(&ComponentLoader::onPeriodic, _1));
Plugable::onAllComponents(boost::bind(&ComponentLoader::onIdle, _1));
diff --git a/project2/cgi/p2webFCgi.cpp b/project2/cgi/p2webFCgi.cpp
index 7eb631f..4320c48 100644
--- a/project2/cgi/p2webFCgi.cpp
+++ b/project2/cgi/p2webFCgi.cpp
@@ -1,6 +1,6 @@
-#include "cgiCommon.h"
#include "FCgiIO.h"
-#include "scriptLoader.h"
+#include "cgiAppEngine.h"
+#include "optionsSource.h"
#include <boost/bind.hpp>
time_t lastPeriodic = 0;
@@ -40,12 +40,15 @@ main(void)
fprintf(stderr, "Failed to set signal handler\n");
}
alarm(60);
- CgiEnvironment env;
Plugable::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1));
+ CgiApplicationEngine app;
while (FCGX_Accept_r(&request) == 0) {
alarm(0);
cgicc::FCgiIO IO(request);
- cgiServe(&IO, &env, IO, &IO);
+ CgiRequestContext crc(&IO, IO);
+ OptionsSource::loadSources(boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc));
+ Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
+ app.process(IO, &crc);
FCGX_Finish_r(&request);
Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1));
if (time(NULL) > lastPeriodic + periodicDelay) {
diff --git a/project2/cgi/pch.hpp b/project2/cgi/pch.hpp
index df744a4..5f68b7c 100644
--- a/project2/cgi/pch.hpp
+++ b/project2/cgi/pch.hpp
@@ -2,14 +2,8 @@
#ifndef CGI_PCH
#define CGI_PCH
-#include "appEngine.h"
-#include "cgiAppEngine.h"
-#include "cgiCommon.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
#include "cgiHttpHeader.h"
-#include "exceptions.h"
-#include "iterate.h"
-#include "logger.h"
#include "scriptLoader.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp
index 9ef0079..2025594 100644
--- a/project2/cgi/testCgi.cpp
+++ b/project2/cgi/testCgi.cpp
@@ -3,8 +3,9 @@
#include <map>
#include "options.h"
#include "safeMapFind.h"
-#include "cgiCommon.h"
#include "../files/optionsSource.h"
+#include "cgiRequestContext.h"
+#include "cgiAppEngine.h"
#define TESTOPT(name, def, desc) \
(name, Options::value(optStore().insert(OptStore::value_type(name, StrPtr(new std::string()))).first->second.get(), def), desc)
@@ -12,8 +13,8 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
public:
class TestConfigConsumer : public ConfigConsumer {
public:
- void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const {
- Plugable::onAll<Options>(boost::bind(&Options::consume, _1, n, p, v));
+ void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v, const Options::CurrentPlatform & cp) const {
+ Plugable::onAll<Options>(boost::bind(&Options::consume, _1, n, p, v, cp));
}
const Options::Option * get(const Glib::ustring &) const {
return NULL;
@@ -22,11 +23,13 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
typedef boost::shared_ptr<std::string> StrPtr;
typedef std::map<std::string, StrPtr> OptStore;
- TestInput(int argc, char ** argv)
+ TestInput(int argc, char ** argv) :
+ crc(NULL, *this)
{
- OptionsSource::loadSources();
+ auto cp = boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc);
+ OptionsSource::loadSources(cp);
FileOptions fo(".testCgi.settings");
- fo.loadInto(TestConfigConsumer());
+ fo.loadInto(TestConfigConsumer(), cp);
if (argc > 1) {
const char * qm = strchr(argv[1], '?');
if (qm) {
@@ -51,9 +54,10 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
}
void run()
{
+ CgiApplicationEngine app;
if (urlListFile.empty()) {
for (int run = 0; run < runCount; run += 1) {
- cgiServe(this, &env, std::cout, this);
+ app.process(std::cout, &crc);
}
}
else {
@@ -63,7 +67,7 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
std::string url;
urls >> url;
optStore()["REDIRECT_URL"] = StrPtr(new std::string(url));
- cgiServe(this, &env, std::cout, this);
+ app.process(std::cout, &crc);
}
}
}
@@ -71,7 +75,7 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
INITOPTIONS;
private:
- CgiEnvironment env;
+ CgiRequestContext crc;
static int runCount;
static std::string urlListFile;
static OptStore & optStore()