diff options
author | randomdan <randomdan@localhost> | 2013-07-05 00:01:26 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2013-07-05 00:01:26 +0000 |
commit | 530d921225b019130585667d91bad25194179310 (patch) | |
tree | 6f3a750f79ad26047ff5322522219798d19aa64c /project2/cgi | |
parent | Move remaining options out of environment (diff) | |
download | project2-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')
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(¬FoundPresent), + "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(¬FoundPresent), - "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() |