summaryrefslogtreecommitdiff
path: root/project2/cgi
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2013-03-23 16:45:24 +0000
committerrandomdan <randomdan@localhost>2013-03-23 16:45:24 +0000
commit983852763e237e7bcca7971679539f915b6ea88d (patch)
treea9c508d6217d7c48ef539c66d4723d17e7553654 /project2/cgi
parentAllow script components to declare themselves uncacheable (diff)
downloadproject2-983852763e237e7bcca7971679539f915b6ea88d.tar.bz2
project2-983852763e237e7bcca7971679539f915b6ea88d.tar.xz
project2-983852763e237e7bcca7971679539f915b6ea88d.zip
Adds a presenter loader that performs basic HTTP content negotiation
Diffstat (limited to 'project2/cgi')
-rw-r--r--project2/cgi/cgiContentNegotiate.cpp57
-rw-r--r--project2/cgi/cgiEnvironment.cpp8
-rw-r--r--project2/cgi/cgiEnvironment.h1
3 files changed, 65 insertions, 1 deletions
diff --git a/project2/cgi/cgiContentNegotiate.cpp b/project2/cgi/cgiContentNegotiate.cpp
new file mode 100644
index 0000000..8e265a8
--- /dev/null
+++ b/project2/cgi/cgiContentNegotiate.cpp
@@ -0,0 +1,57 @@
+#include <pch.hpp>
+#include "cgiAppEngine.h"
+#include <boost/tokenizer.hpp>
+
+class ContentNegotiateLoader : public PresenterLoader {
+ public:
+ ContentNegotiateLoader() :
+ opts("Content negotiation options")
+ {
+ opts
+ ("cgi.contentnegotiation.mappedtype", Options::value(&mappedTypes),
+ "mimetype=presenter list of types to negotiate")
+ ;
+ }
+
+ const Options * options() const { return &opts; }
+
+ MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os) const
+ {
+ auto accept = static_cast<const CgiApplicationEngine *>(CgiApplicationEngine::getCurrent())->env()->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(mappedTypes.begin()->present)->create(s, os);
+ }
+
+ Options opts;
+ class MappedType {
+ public:
+ MappedType(const std::string & val) :
+ accept(val.substr(0, val.find('='))),
+ present(val.substr(val.find('=') + 1))
+ {
+ }
+
+ bool Matches(const std::string & a) const
+ {
+ return (accept == a);
+ }
+
+ const std::string accept;
+ const std::string present;
+ };
+ std::vector<MappedType> mappedTypes;
+
+ bool cacheable() const { return false; }
+};
+
+DECLARE_CUSTOM_COMPONENT_LOADER("contentnegotiate", ContentNegotiateLoader, ContentNegotiateLoader, PresenterLoader);
+
diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp
index 292a52f..c106f67 100644
--- a/project2/cgi/cgiEnvironment.cpp
+++ b/project2/cgi/cgiEnvironment.cpp
@@ -30,7 +30,7 @@ CgiEnvironment::CgiEnvironment() :
"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, "text/xml"),
+ ("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")
@@ -101,6 +101,12 @@ CgiEnvironment::getServerName() const
return cgi->getEnvironment().getServerName();
}
+std::string
+CgiEnvironment::getAccept() const
+{
+ return cgi->getEnvironment().getAccept();
+}
+
const Glib::ustring &
CgiEnvironment::platform() const
{
diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h
index dd89a75..330cd97 100644
--- a/project2/cgi/cgiEnvironment.h
+++ b/project2/cgi/cgiEnvironment.h
@@ -42,6 +42,7 @@ class CgiEnvironment : public Environment {
std::string getScriptName() 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;