summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--icespider/core/Jamfile.jam2
-rw-r--r--icespider/core/util.h8
-rw-r--r--icespider/fcgi/Jamfile.jam3
-rw-r--r--icespider/fcgi/cgiRequest.cpp25
-rw-r--r--icespider/fcgi/cgiRequest.h17
-rw-r--r--icespider/fcgi/cgiRequestBase.cpp99
-rw-r--r--icespider/fcgi/cgiRequestBase.h38
-rw-r--r--icespider/fcgi/fcgiRequest.cpp26
-rw-r--r--icespider/fcgi/fcgiRequest.h23
-rw-r--r--icespider/fcgi/main.cpp18
-rw-r--r--icespider/unittests/Jamfile.jam10
-rw-r--r--icespider/unittests/testFcgi.cpp1
12 files changed, 265 insertions, 5 deletions
diff --git a/icespider/core/Jamfile.jam b/icespider/core/Jamfile.jam
index 6a99e84..5dbaf31 100644
--- a/icespider/core/Jamfile.jam
+++ b/icespider/core/Jamfile.jam
@@ -12,4 +12,6 @@ lib icespider-core :
<implicit-dependency>../common
: :
<include>.
+ <library>../common
+ <implicit-dependency>../common
;
diff --git a/icespider/core/util.h b/icespider/core/util.h
index 075f237..03a01a9 100644
--- a/icespider/core/util.h
+++ b/icespider/core/util.h
@@ -12,5 +12,13 @@ namespace IceUtil {
}
}
+template <typename T>
+T orelse(const T & a, const T & b)
+{
+ if (a) return a;
+ return b;
+}
+
+
#endif
diff --git a/icespider/fcgi/Jamfile.jam b/icespider/fcgi/Jamfile.jam
index eb0c3f2..c607ed1 100644
--- a/icespider/fcgi/Jamfile.jam
+++ b/icespider/fcgi/Jamfile.jam
@@ -1,7 +1,10 @@
lib fcgi : : <name>fcgi ;
+lib fcgi++ : : <name>fcgi++ ;
lib icespider-fcgi :
[ glob-tree *.cpp : bin ]
:
<library>fcgi
+ <library>fcgi++
+ <library>..//core
;
diff --git a/icespider/fcgi/cgiRequest.cpp b/icespider/fcgi/cgiRequest.cpp
new file mode 100644
index 0000000..abc3bea
--- /dev/null
+++ b/icespider/fcgi/cgiRequest.cpp
@@ -0,0 +1,25 @@
+#include "cgiRequest.h"
+
+namespace IceSpider {
+ CgiRequest::CgiRequest(IceSpider::Core * c, int argc, char ** argv, char ** env) :
+ CgiRequestBase(c, env)
+ {
+ for (; argc > 0;) {
+ addenv(argv[--argc]);
+ }
+ initialize();
+ }
+
+ std::istream &
+ CgiRequest::getInputStream() const
+ {
+ return std::cin;
+ }
+
+ std::ostream &
+ CgiRequest::getOutputStream() const
+ {
+ return std::cout;
+ }
+}
+
diff --git a/icespider/fcgi/cgiRequest.h b/icespider/fcgi/cgiRequest.h
new file mode 100644
index 0000000..9af58bb
--- /dev/null
+++ b/icespider/fcgi/cgiRequest.h
@@ -0,0 +1,17 @@
+#ifndef ICESPIDER_CGI_CGIREQUEST_H
+#define ICESPIDER_CGI_CGIREQUEST_H
+
+#include "cgiRequestBase.h"
+
+namespace IceSpider {
+ class CgiRequest : public CgiRequestBase {
+ public:
+ CgiRequest(IceSpider::Core * c, int argc, char ** argv, char ** env);
+
+ std::istream & getInputStream() const override;
+ std::ostream & getOutputStream() const override;
+ };
+}
+
+#endif
+
diff --git a/icespider/fcgi/cgiRequestBase.cpp b/icespider/fcgi/cgiRequestBase.cpp
new file mode 100644
index 0000000..97a71fc
--- /dev/null
+++ b/icespider/fcgi/cgiRequestBase.cpp
@@ -0,0 +1,99 @@
+#include "cgiRequestBase.h"
+#include <boost/algorithm/string/case_conv.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <util.h>
+
+namespace ba = boost::algorithm;
+
+namespace IceSpider {
+ CgiRequestBase::CgiRequestBase(IceSpider::Core * c, char ** env) :
+ IceSpider::IHttpRequest(c)
+ {
+ for(char * const * e = env; *e; ++e) {
+ addenv(*e);
+ }
+ }
+
+ void
+ CgiRequestBase::addenv(char * e)
+ {
+ if (auto eq = strchr(e, '=')) {
+ *eq++ = '\0';
+ envmap.insert({ e, Env(eq, strchr(eq, '\0')) });
+ }
+ }
+
+ void
+ CgiRequestBase::initialize()
+ {
+ auto qs = envmap.find("QUERY_STRING");
+ if (qs != envmap.end()) {
+ auto start = std::get<0>(qs->second);
+ auto end = std::get<1>(qs->second);
+ while (start < end) {
+ auto amp = orelse(strchr(start, '&'), end);
+ auto eq = orelse(strchr(start, '='), end);
+ if (eq < amp) {
+ *eq = '\0';
+ *amp = '\0';
+ qsmap.insert({ eq, Env( eq + 1, amp ) });
+ }
+ else {
+ *eq = '\0';
+ *amp = '\0';
+ qsmap.insert({ eq, Env( eq + 1, eq + 1 ) });
+ }
+ start = amp + 1;
+ }
+ }
+ }
+
+ IceUtil::Optional<std::string>
+ CgiRequestBase::optionalLookup(const std::string & key, const VarMap & vm)
+ {
+ auto i = vm.find(key.c_str());
+ if (i == vm.end()) {
+ return IceUtil::Optional<std::string>();
+ }
+ return std::string(std::get<0>(i->second), std::get<1>(i->second));
+ }
+
+ std::string
+ CgiRequestBase::getRequestPath() const
+ {
+ return optionalLookup("REDIRECT_URL", envmap) /
+ [this]() { return optionalLookup("SCRIPT_NAME", envmap); } /
+ [this]() -> std::string { throw std::runtime_error("Couldn't determine request path"); };
+ }
+
+ UserIceSpider::HttpMethod
+ CgiRequestBase::getRequestMethod() const
+ {
+ return UserIceSpider::HttpMethod::GET;
+ }
+
+ IceUtil::Optional<std::string>
+ CgiRequestBase::getURLParam(const std::string & key) const
+ {
+ return optionalLookup(key, pathmap);
+ }
+
+ IceUtil::Optional<std::string>
+ CgiRequestBase::getQueryStringParam(const std::string & key) const
+ {
+ return optionalLookup(key, qsmap);
+ }
+
+ IceUtil::Optional<std::string>
+ CgiRequestBase::getHeaderParam(const std::string & key) const
+ {
+ return optionalLookup(("HTTP_" + boost::algorithm::to_upper_copy(key)).c_str(), envmap);
+ }
+
+ bool
+ CgiRequestBase::cmp_str::operator()(char const * a, char const * b) const
+ {
+ return std::strcmp(a, b) < 0;
+ }
+}
+
diff --git a/icespider/fcgi/cgiRequestBase.h b/icespider/fcgi/cgiRequestBase.h
new file mode 100644
index 0000000..8a6d207
--- /dev/null
+++ b/icespider/fcgi/cgiRequestBase.h
@@ -0,0 +1,38 @@
+#ifndef ICESPIDER_CGI_CGIREQUESTBASE_H
+#define ICESPIDER_CGI_CGIREQUESTBASE_H
+
+#include <core.h>
+#include <ihttpRequest.h>
+#include <map>
+#include <tuple>
+
+namespace IceSpider {
+ class CgiRequestBase : public IceSpider::IHttpRequest {
+ protected:
+ struct cmp_str {
+ bool operator()(char const *a, char const *b) const;
+ };
+
+ typedef std::tuple<char *, char *> Env;
+ typedef std::map<const char *, Env, cmp_str> VarMap;
+
+ CgiRequestBase(IceSpider::Core * c, char ** env);
+ void addenv(char *);
+ void initialize();
+
+ std::string getRequestPath() const override;
+ UserIceSpider::HttpMethod getRequestMethod() const override;
+ IceUtil::Optional<std::string> getURLParam(const std::string & key) const override;
+ IceUtil::Optional<std::string> getQueryStringParam(const std::string & key) const override;
+ IceUtil::Optional<std::string> getHeaderParam(const std::string & key) const override;
+
+ static IceUtil::Optional<std::string> optionalLookup(const std::string & key, const VarMap &);
+
+ VarMap envmap;
+ VarMap qsmap;
+ VarMap pathmap;
+ };
+}
+
+#endif
+
diff --git a/icespider/fcgi/fcgiRequest.cpp b/icespider/fcgi/fcgiRequest.cpp
new file mode 100644
index 0000000..484f12f
--- /dev/null
+++ b/icespider/fcgi/fcgiRequest.cpp
@@ -0,0 +1,26 @@
+#include "fcgiRequest.h"
+
+namespace IceSpider {
+ FcgiRequest::FcgiRequest(IceSpider::Core * c, FCGX_Request * r) :
+ CgiRequestBase(c, r->envp),
+ inputbuf(r->in),
+ input(&inputbuf),
+ outputbuf(r->out),
+ output(&outputbuf)
+ {
+ initialize();
+ }
+
+ std::istream &
+ FcgiRequest::getInputStream() const
+ {
+ return input;
+ }
+
+ std::ostream &
+ FcgiRequest::getOutputStream() const
+ {
+ return output;
+ }
+}
+
diff --git a/icespider/fcgi/fcgiRequest.h b/icespider/fcgi/fcgiRequest.h
new file mode 100644
index 0000000..ec5b65b
--- /dev/null
+++ b/icespider/fcgi/fcgiRequest.h
@@ -0,0 +1,23 @@
+#ifndef ICESPIDER_CGI_FCGIREQUEST_H
+#define ICESPIDER_CGI_FCGIREQUEST_H
+
+#include "cgiRequestBase.h"
+#include <fcgio.h>
+
+namespace IceSpider {
+ class FcgiRequest : public CgiRequestBase {
+ public:
+ FcgiRequest(IceSpider::Core * c, FCGX_Request * r);
+
+ std::istream & getInputStream() const override;
+ std::ostream & getOutputStream() const override;
+
+ fcgi_streambuf inputbuf;
+ mutable std::istream input;
+ fcgi_streambuf outputbuf;
+ mutable std::ostream output;
+ };
+}
+
+#endif
+
diff --git a/icespider/fcgi/main.cpp b/icespider/fcgi/main.cpp
index 6132769..1d2e68c 100644
--- a/icespider/fcgi/main.cpp
+++ b/icespider/fcgi/main.cpp
@@ -1,8 +1,14 @@
-#include <fcgio.h>
+#include <visibility.h>
+#include "fcgiRequest.h"
+#include "cgiRequest.h"
+using namespace IceSpider;
+
+DLL_PUBLIC
int
-main(void)
+main(int argc, char ** argv, char ** env)
{
+ IceSpider::Core core;
if (!FCGX_IsCGI()) {
FCGX_Request request;
@@ -10,13 +16,15 @@ main(void)
FCGX_InitRequest(&request, 0, 0);
while (FCGX_Accept_r(&request) == 0) {
- // app.process(IO, &IO, IO);
+ FcgiRequest r(&core, &request);
+ core.process(&r);
FCGX_Finish_r(&request);
}
- return 0;
}
else {
- return 1;
+ CgiRequest r(&core, argc, argv, env);
+ core.process(&r);
}
+ return 0;
}
diff --git a/icespider/unittests/Jamfile.jam b/icespider/unittests/Jamfile.jam
index b9a861b..d948b29 100644
--- a/icespider/unittests/Jamfile.jam
+++ b/icespider/unittests/Jamfile.jam
@@ -69,6 +69,16 @@ run
<dependency>../compile
: testApp ;
+run
+ testFcgi.cpp
+ :
+ 'QUERY_STRING=noeq&noval=&someval=here&another=here'
+ 'REDIRECT_URL=/'
+ : :
+ <library>../common//icespider-common
+ <library>../core//icespider-core
+ <library>../fcgi//icespider-fcgi
+ : testFcgi ;
lib test-api :
test-api.ice
diff --git a/icespider/unittests/testFcgi.cpp b/icespider/unittests/testFcgi.cpp
new file mode 100644
index 0000000..65e2cc3
--- /dev/null
+++ b/icespider/unittests/testFcgi.cpp
@@ -0,0 +1 @@
+// intentionally blank