From e64c2e32f48291a38cd8aba38f47107da4bf6868 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 9 Oct 2016 00:54:50 +0100 Subject: Add support for cookie parameters --- icespider/common/http.ice | 2 +- icespider/core/ihttpRequest.cpp | 4 ++++ icespider/core/ihttpRequest.h | 3 +++ icespider/fcgi/cgiRequestBase.cpp | 14 +++++++++++++- icespider/fcgi/cgiRequestBase.h | 2 ++ icespider/fcgi/xwwwFormUrlEncoded.cpp | 6 +++--- icespider/fcgi/xwwwFormUrlEncoded.h | 2 +- icespider/unittests/testApp.cpp | 20 ++++++++++++++++++-- icespider/unittests/testCompile.cpp | 4 ++-- icespider/unittests/testFcgi.cpp | 9 +++++++++ icespider/unittests/testRoutes.json | 14 ++++++++++++++ 11 files changed, 70 insertions(+), 10 deletions(-) diff --git a/icespider/common/http.ice b/icespider/common/http.ice index d4f07b0..fa85f02 100644 --- a/icespider/common/http.ice +++ b/icespider/common/http.ice @@ -13,7 +13,7 @@ module IceSpider { }; enum ParameterSource { - URL, Body, QueryString, Header + URL, Body, QueryString, Header, Cookie }; ["slicer:ignore"] diff --git a/icespider/core/ihttpRequest.cpp b/icespider/core/ihttpRequest.cpp index bd4d790..6f68f5f 100644 --- a/icespider/core/ihttpRequest.cpp +++ b/icespider/core/ihttpRequest.cpp @@ -113,12 +113,16 @@ namespace IceSpider { return wrapLexicalCast(getURLParam(idx)); } \ template<> IceUtil::Optional IHttpRequest::getQueryStringParam(const std::string & key) const { \ return optionalLexicalCast(getQueryStringParam(key)); } \ + template<> IceUtil::Optional IHttpRequest::getCookieParam(const std::string & key) const { \ + return optionalLexicalCast(getCookieParam(key)); } \ template<> IceUtil::Optional IHttpRequest::getHeaderParam(const std::string & key) const { \ return optionalLexicalCast(getHeaderParam(key)); } template<> std::string IHttpRequest::getURLParam(unsigned int idx) const { return getURLParam(idx); } template<> IceUtil::Optional IHttpRequest::getQueryStringParam(const std::string & key) const { \ return getQueryStringParam(key); } + template<> IceUtil::Optional IHttpRequest::getCookieParam(const std::string & key) const { \ + return getCookieParam(key); } template<> IceUtil::Optional IHttpRequest::getHeaderParam(const std::string & key) const { \ return getHeaderParam(key); } diff --git a/icespider/core/ihttpRequest.h b/icespider/core/ihttpRequest.h index 6f6d300..92435f4 100644 --- a/icespider/core/ihttpRequest.h +++ b/icespider/core/ihttpRequest.h @@ -29,6 +29,7 @@ namespace IceSpider { const std::string & getURLParam(unsigned int) const; virtual OptionalString getQueryStringParam(const std::string &) const = 0; virtual OptionalString getHeaderParam(const std::string &) const = 0; + virtual OptionalString getCookieParam(const std::string &) const = 0; virtual OptionalString getEnv(const std::string &) const = 0; virtual Slicer::DeserializerPtr getDeserializer() const; virtual ContentTypeSerializer getSerializer(const IRouteHandler *) const; @@ -60,6 +61,8 @@ namespace IceSpider { IceUtil::Optional getQueryStringParam(const std::string & key) const; template IceUtil::Optional getHeaderParam(const std::string & key) const; + template + IceUtil::Optional getCookieParam(const std::string & key) const; void response(short, const std::string &) const; template void response(const IRouteHandler * route, const T & t) const diff --git a/icespider/fcgi/cgiRequestBase.cpp b/icespider/fcgi/cgiRequestBase.cpp index efa9468..eb141c2 100644 --- a/icespider/fcgi/cgiRequestBase.cpp +++ b/icespider/fcgi/cgiRequestBase.cpp @@ -43,7 +43,13 @@ namespace IceSpider { if (qs != envmap.end()) { XWwwFormUrlEncoded::iterateVars(std::string(std::get<0>(qs->second), std::get<1>(qs->second)), [this](auto k, auto v) { qsmap.insert({ k, v }); - }); + }, "&"); + } + auto cs = envmap.find("HTTP_COOKIE"); + if (cs != envmap.end()) { + XWwwFormUrlEncoded::iterateVars(std::string(std::get<0>(cs->second), std::get<1>(cs->second)), [this](auto k, auto v) { + cookiemap.insert({ k, v }); + }, "; "); } } @@ -92,6 +98,12 @@ namespace IceSpider { return optionalLookup(key, qsmap); } + OptionalString + CgiRequestBase::getCookieParam(const std::string & key) const + { + return optionalLookup(key, cookiemap); + } + OptionalString CgiRequestBase::getEnv(const std::string & key) const { diff --git a/icespider/fcgi/cgiRequestBase.h b/icespider/fcgi/cgiRequestBase.h index 20d7d05..1cfcacc 100644 --- a/icespider/fcgi/cgiRequestBase.h +++ b/icespider/fcgi/cgiRequestBase.h @@ -25,6 +25,7 @@ namespace IceSpider { HttpMethod getRequestMethod() const override; OptionalString getQueryStringParam(const std::string & key) const override; OptionalString getHeaderParam(const std::string & key) const override; + OptionalString getCookieParam(const std::string & key) const override; OptionalString getEnv(const std::string & key) const override; private: @@ -33,6 +34,7 @@ namespace IceSpider { VarMap envmap; StringMap qsmap; + StringMap cookiemap; PathElements pathElements; }; } diff --git a/icespider/fcgi/xwwwFormUrlEncoded.cpp b/icespider/fcgi/xwwwFormUrlEncoded.cpp index 2f60367..345a597 100644 --- a/icespider/fcgi/xwwwFormUrlEncoded.cpp +++ b/icespider/fcgi/xwwwFormUrlEncoded.cpp @@ -101,17 +101,17 @@ namespace IceSpider { } void - XWwwFormUrlEncoded::iterateVars(const std::string & input, const KVh & h) + XWwwFormUrlEncoded::iterateVars(const std::string & input, const KVh & h, const std::string & split) { if (!input.empty()) { - iterateVars(h, ba::make_split_iterator(input, ba::first_finder("&", ba::is_equal()))); + iterateVars(h, ba::make_split_iterator(input, ba::first_finder(split, ba::is_equal()))); } } void XWwwFormUrlEncoded::iterateVars(const KVh & h) { - iterateVars(input, h); + iterateVars(input, h, "&"); } void diff --git a/icespider/fcgi/xwwwFormUrlEncoded.h b/icespider/fcgi/xwwwFormUrlEncoded.h index fe6aa00..54205e3 100644 --- a/icespider/fcgi/xwwwFormUrlEncoded.h +++ b/icespider/fcgi/xwwwFormUrlEncoded.h @@ -12,7 +12,7 @@ namespace IceSpider { XWwwFormUrlEncoded(std::istream & in); void Deserialize(Slicer::ModelPartForRootPtr mp) override; - static inline void iterateVars(const std::string & input, const KVh & h); + static void iterateVars(const std::string & input, const KVh & h, const std::string & split); private: diff --git a/icespider/unittests/testApp.cpp b/icespider/unittests/testApp.cpp index ddf1579..de5e921 100644 --- a/icespider/unittests/testApp.cpp +++ b/icespider/unittests/testApp.cpp @@ -28,7 +28,7 @@ void forceEarlyChangeDir() BOOST_AUTO_TEST_CASE( testLoadConfiguration ) { - BOOST_REQUIRE_EQUAL(11, AdHoc::PluginManager::getDefault()->getAll().size()); + BOOST_REQUIRE_EQUAL(12, AdHoc::PluginManager::getDefault()->getAll().size()); } class TestRequest : public IHttpRequest { @@ -64,6 +64,11 @@ class TestRequest : public IHttpRequest { return qs.find(key) == qs.end() ? IceUtil::Optional() : qs.find(key)->second; } + IceUtil::Optional getCookieParam(const std::string & key) const override + { + return cookies.find(key) == cookies.end() ? IceUtil::Optional() : cookies.find(key)->second; + } + IceUtil::Optional getHeaderParam(const std::string & key) const override { return hdr.find(key) == hdr.end() ? IceUtil::Optional() : hdr.find(key)->second; @@ -83,6 +88,7 @@ class TestRequest : public IHttpRequest { typedef std::vector UrlVars; UrlVars url; MapVars qs; + MapVars cookies; MapVars hdr; MapVars env; mutable std::stringstream input; @@ -144,7 +150,7 @@ BOOST_AUTO_TEST_CASE( testCoreSettings ) { BOOST_REQUIRE_EQUAL(5, routes.size()); BOOST_REQUIRE_EQUAL(1, routes[0].size()); - BOOST_REQUIRE_EQUAL(5, routes[1].size()); + BOOST_REQUIRE_EQUAL(6, routes[1].size()); BOOST_REQUIRE_EQUAL(1, routes[2].size()); BOOST_REQUIRE_EQUAL(2, routes[3].size()); BOOST_REQUIRE_EQUAL(2, routes[4].size()); @@ -543,5 +549,15 @@ BOOST_AUTO_TEST_CASE( testCallSearchMissingI ) BOOST_REQUIRE(request.output.eof()); } +BOOST_AUTO_TEST_CASE( testCookies ) +{ + TestRequest request(this, HttpMethod::GET, "/cookies"); + request.cookies["mycookievar"] = "something"; + request.qs["i"] = "1234"; + process(&request); + auto h = parseHeaders(request.output); + BOOST_REQUIRE_EQUAL(h["Status"], "200 OK"); +} + BOOST_AUTO_TEST_SUITE_END(); diff --git a/icespider/unittests/testCompile.cpp b/icespider/unittests/testCompile.cpp index 8d1cefa..0d7e36c 100644 --- a/icespider/unittests/testCompile.cpp +++ b/icespider/unittests/testCompile.cpp @@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE( testLoadConfiguration ) rc.applyDefaults(cfg, u); BOOST_REQUIRE_EQUAL("common", cfg->name); - BOOST_REQUIRE_EQUAL(11, cfg->routes.size()); + BOOST_REQUIRE_EQUAL(12, cfg->routes.size()); BOOST_REQUIRE_EQUAL("/", cfg->routes["index"]->path); BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes["index"]->method); @@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE( testLoad ) BOOST_TEST_INFO(dlerror()); BOOST_REQUIRE(lib); - BOOST_REQUIRE_EQUAL(11, AdHoc::PluginManager::getDefault()->getAll().size()); + BOOST_REQUIRE_EQUAL(12, AdHoc::PluginManager::getDefault()->getAll().size()); // smoke test (block ensure dlclose dones't cause segfault) { auto route = AdHoc::PluginManager::getDefault()->get("common::index"); diff --git a/icespider/unittests/testFcgi.cpp b/icespider/unittests/testFcgi.cpp index 923c28d..2c93c32 100644 --- a/icespider/unittests/testFcgi.cpp +++ b/icespider/unittests/testFcgi.cpp @@ -264,5 +264,14 @@ BOOST_AUTO_TEST_CASE( postjson_dictionary ) BOOST_REQUIRE_EQUAL("", n["empty"]); } +BOOST_AUTO_TEST_CASE( cookies ) +{ + CharPtrPtrArray env ({ "SCRIPT_NAME=/", "REQUEST_METHOD=No", "CONTENT_TYPE=application/json", "HTTP_COOKIE=valueA=1234; value+B=Something+with+spaces." }); + TestRequest r(this, env); + BOOST_REQUIRE_EQUAL(1234, *r.IceSpider::IHttpRequest::getCookieParam("valueA")); + BOOST_REQUIRE_EQUAL("Something with spaces.", *r.IceSpider::IHttpRequest::getCookieParam("value B")); + BOOST_REQUIRE(!r.IceSpider::IHttpRequest::getCookieParam("notAThing")); +} + BOOST_AUTO_TEST_SUITE_END(); diff --git a/icespider/unittests/testRoutes.json b/icespider/unittests/testRoutes.json index 5bf002f..3bc6fda 100644 --- a/icespider/unittests/testRoutes.json +++ b/icespider/unittests/testRoutes.json @@ -124,6 +124,20 @@ "source": "QueryString" } } + }, + "cookies": { + "path": "/cookies", + "method": "GET", + "operation": "TestIceSpider.TestApi.withParams", + "params": { + "s": { + "source": "Cookie", + "key": "mycookievar" + }, + "i": { + "source": "QueryString" + } + } } }, "slices": [ -- cgit v1.2.3