diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-06-26 12:40:30 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-06-26 12:40:30 +0100 |
commit | e548772e83997fd2b1cdf1473b68e912ee986018 (patch) | |
tree | 2aef1b314709d88585dd8f225a62e27259743cc9 | |
parent | Default parameter expressions (diff) | |
download | icespider-e548772e83997fd2b1cdf1473b68e912ee986018.tar.bz2 icespider-e548772e83997fd2b1cdf1473b68e912ee986018.tar.xz icespider-e548772e83997fd2b1cdf1473b68e912ee986018.zip |
URL parameters by index internally, not key
-rw-r--r-- | icespider/compile/routeCompiler.cpp | 31 | ||||
-rw-r--r-- | icespider/core/core.cpp | 10 | ||||
-rw-r--r-- | icespider/core/ihttpRequest.cpp | 18 | ||||
-rw-r--r-- | icespider/core/ihttpRequest.h | 6 | ||||
-rw-r--r-- | icespider/core/irouteHandler.h | 8 | ||||
-rw-r--r-- | icespider/fcgi/cgiRequestBase.cpp | 22 | ||||
-rw-r--r-- | icespider/fcgi/cgiRequestBase.h | 6 | ||||
-rw-r--r-- | icespider/unittests/testApp.cpp | 30 |
8 files changed, 76 insertions, 55 deletions
diff --git a/icespider/compile/routeCompiler.cpp b/icespider/compile/routeCompiler.cpp index b28231e..8064946 100644 --- a/icespider/compile/routeCompiler.cpp +++ b/icespider/compile/routeCompiler.cpp @@ -226,7 +226,21 @@ namespace IceSpider { for (const auto & p : r->params) { if (p->hasUserSource) { fprintf(output, ",\n"); - fprintbf(4, output, "_pn_%s(\"%s\")", p->name, *p->key); + if (p->source == UserIceSpider::ParameterSource::URL) { + IceSpider::Path path(r->path); + unsigned int idx = -1; + for (const auto & pp : path.parts) { + if (auto par = dynamic_cast<PathParameter *>(pp.get())) { + if (par->name == p->key) { + idx = &pp - &path.parts.front(); + } + } + }; + fprintbf(4, output, "_pi_%s(%d)", p->name, idx); + } + else { + fprintbf(4, output, "_pn_%s(\"%s\")", p->name, *p->key); + } } if (p->defaultExpr) { fprintf(output, ",\n"); @@ -243,9 +257,11 @@ namespace IceSpider { for (const auto & p : r->params) { if (p->hasUserSource) { auto ip = *std::find_if(o->parameters().begin(), o->parameters().end(), [p](const auto & ip) { return ip->name() == p->name; }); - fprintbf(4, output, "auto _p_%s(request->get%sParam<%s>(_pn_%s)", - p->name, getEnumString(p->source), Slice::typeToString(ip->type()), p->name); - if (!p->isOptional) { + fprintbf(4, output, "auto _p_%s(request->get%sParam<%s>(_p%c_%s)", + p->name, getEnumString(p->source), Slice::typeToString(ip->type()), + p->source == UserIceSpider::ParameterSource::URL ? 'i' : 'n', + p->name); + if (!p->isOptional && p->source != UserIceSpider::ParameterSource::URL) { fprintbf(0, output, " /\n"); if (p->defaultExpr) { fprintbf(5, output, " [this]() { return _pd_%s; }", @@ -289,7 +305,12 @@ namespace IceSpider { fprintbf(2, output, "private:\n"); for (const auto & p : r->params) { if (p->hasUserSource) { - fprintbf(3, output, "const std::string _pn_%s;\n", p->name); + if (p->source == UserIceSpider::ParameterSource::URL) { + fprintbf(3, output, "const unsigned int _pi_%s;\n", p->name); + } + else { + fprintbf(3, output, "const std::string _pn_%s;\n", p->name); + } } if (p->defaultExpr) { auto ip = *std::find_if(o->parameters().begin(), o->parameters().end(), [p](const auto & ip) { return ip->name() == p->name; }); diff --git a/icespider/core/core.cpp b/icespider/core/core.cpp index 5509580..35af72f 100644 --- a/icespider/core/core.cpp +++ b/icespider/core/core.cpp @@ -1,10 +1,6 @@ #include "core.h" -#include <boost/algorithm/string/split.hpp> -#include <boost/algorithm/string/classification.hpp> #include <Ice/Initialize.h> -namespace ba = boost::algorithm; - namespace IceSpider { Core::Core(int argc, char ** argv) { @@ -45,12 +41,8 @@ namespace IceSpider { const IRouteHandler * Core::findRoute(const IHttpRequest * request) const { - auto path = request->getRequestPath().substr(1); + auto & pathparts = request->getRequestPath(); const auto & mroutes = routes[request->getRequestMethod()]; - std::vector<std::string> pathparts; - if (!path.empty()) { - ba::split(pathparts, path, ba::is_any_of("/"), ba::token_compress_off); - } if (pathparts.size() >= mroutes.size()) { // Not found error return NULL; diff --git a/icespider/core/ihttpRequest.cpp b/icespider/core/ihttpRequest.cpp index a352dca..0dd2aea 100644 --- a/icespider/core/ihttpRequest.cpp +++ b/icespider/core/ihttpRequest.cpp @@ -30,6 +30,16 @@ namespace IceSpider { "application/json", getOutputStream()); } + const std::string & + IHttpRequest::getURLParam(unsigned int idx) const + { + auto & url = getRequestPath(); + if (idx >= url.size()) { + throw std::runtime_error("Bad Url parameter index"); + } + return url[idx]; + } + template <typename T> inline IceUtil::Optional<T> optionalLexicalCast(const IceUtil::Optional<std::string> & p) { @@ -46,14 +56,14 @@ namespace IceSpider { #define getParams(T) \ - template<> IceUtil::Optional<T> IHttpRequest::getURLParam<T>(const std::string & key) const { \ - return optionalLexicalCast<T>(getURLParam(key)); } \ + template<> T IHttpRequest::getURLParam<T>(unsigned int idx) const { \ + return boost::lexical_cast<T>(getURLParam(idx)); } \ template<> IceUtil::Optional<T> IHttpRequest::getQueryStringParam<T>(const std::string & key) const { \ return optionalLexicalCast<T>(getQueryStringParam(key)); } \ template<> IceUtil::Optional<T> IHttpRequest::getHeaderParam<T>(const std::string & key) const { \ return optionalLexicalCast<T>(getHeaderParam(key)); } - template<> IceUtil::Optional<std::string> IHttpRequest::getURLParam<std::string>(const std::string & key) const { \ - return getURLParam(key); } + template<> std::string IHttpRequest::getURLParam<std::string>(unsigned int idx) const { + return getURLParam(idx); } template<> IceUtil::Optional<std::string> IHttpRequest::getQueryStringParam<std::string>(const std::string & key) const { \ return getQueryStringParam(key); } template<> IceUtil::Optional<std::string> IHttpRequest::getHeaderParam<std::string>(const std::string & key) const { \ diff --git a/icespider/core/ihttpRequest.h b/icespider/core/ihttpRequest.h index 14dccda..c52ee46 100644 --- a/icespider/core/ihttpRequest.h +++ b/icespider/core/ihttpRequest.h @@ -17,10 +17,10 @@ namespace IceSpider { IHttpRequest(const Core *); Ice::Context getContext() const; - virtual std::string getRequestPath() const = 0; + virtual const std::vector<std::string> & getRequestPath() const = 0; virtual UserIceSpider::HttpMethod getRequestMethod() const = 0; - virtual IceUtil::Optional<std::string> getURLParam(const std::string &) const = 0; + const std::string & getURLParam(unsigned int) const; virtual IceUtil::Optional<std::string> getQueryStringParam(const std::string &) const = 0; virtual IceUtil::Optional<std::string> getHeaderParam(const std::string &) const = 0; virtual Slicer::DeserializerPtr getDeserializer() const; @@ -29,7 +29,7 @@ namespace IceSpider { virtual std::ostream & getOutputStream() const = 0; template<typename T> - IceUtil::Optional<T> getURLParam(const std::string & key) const; + T getURLParam(unsigned int) const; template<typename T> IceUtil::Optional<T> getBodyParam(const std::string &) const { diff --git a/icespider/core/irouteHandler.h b/icespider/core/irouteHandler.h index 32513ae..969ca86 100644 --- a/icespider/core/irouteHandler.h +++ b/icespider/core/irouteHandler.h @@ -7,6 +7,7 @@ #include <routes.h> #include <plugins.h> #include <visibility.h> +#include <boost/lexical_cast.hpp> namespace IceSpider { class DLL_PUBLIC IRouteHandler : public AdHoc::AbstractPluginImplementation, public Path { @@ -17,10 +18,11 @@ namespace IceSpider { const UserIceSpider::HttpMethod method; protected: - template <typename T> - inline T requiredParameterNotFound(const char *, const std::string & key) const + template <typename T, typename K> + inline T requiredParameterNotFound(const char *, const K & key) const { - throw std::runtime_error("Required parameter not found: " + key); + throw std::runtime_error("Required parameter not found: " + + boost::lexical_cast<std::string>(key)); } Ice::ObjectPrx getProxy(IHttpRequest *, const char *) const; diff --git a/icespider/fcgi/cgiRequestBase.cpp b/icespider/fcgi/cgiRequestBase.cpp index 97a71fc..ec9836b 100644 --- a/icespider/fcgi/cgiRequestBase.cpp +++ b/icespider/fcgi/cgiRequestBase.cpp @@ -1,6 +1,7 @@ #include "cgiRequestBase.h" #include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/classification.hpp> #include <util.h> namespace ba = boost::algorithm; @@ -26,6 +27,15 @@ namespace IceSpider { void CgiRequestBase::initialize() { + namespace ba = boost::algorithm; + auto path = (optionalLookup("REDIRECT_URL", envmap) / + [this]() { return optionalLookup("SCRIPT_NAME", envmap); } / + [this]() -> std::string { throw std::runtime_error("Couldn't determine request path"); }) + .substr(1); + if (!path.empty()) { + ba::split(pathmap, path, ba::is_any_of("/"), ba::token_compress_off); + } + auto qs = envmap.find("QUERY_STRING"); if (qs != envmap.end()) { auto start = std::get<0>(qs->second); @@ -58,12 +68,10 @@ namespace IceSpider { return std::string(std::get<0>(i->second), std::get<1>(i->second)); } - std::string + const std::vector<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"); }; + return pathmap; } UserIceSpider::HttpMethod @@ -73,12 +81,6 @@ namespace IceSpider { } 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); diff --git a/icespider/fcgi/cgiRequestBase.h b/icespider/fcgi/cgiRequestBase.h index 8a6d207..8f5b613 100644 --- a/icespider/fcgi/cgiRequestBase.h +++ b/icespider/fcgi/cgiRequestBase.h @@ -15,14 +15,14 @@ namespace IceSpider { typedef std::tuple<char *, char *> Env; typedef std::map<const char *, Env, cmp_str> VarMap; + typedef std::vector<std::string> UrlMap; CgiRequestBase(IceSpider::Core * c, char ** env); void addenv(char *); void initialize(); - std::string getRequestPath() const override; + const std::vector<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; @@ -30,7 +30,7 @@ namespace IceSpider { VarMap envmap; VarMap qsmap; - VarMap pathmap; + UrlMap pathmap; }; } diff --git a/icespider/unittests/testApp.cpp b/icespider/unittests/testApp.cpp index b5af516..cf14c81 100644 --- a/icespider/unittests/testApp.cpp +++ b/icespider/unittests/testApp.cpp @@ -7,6 +7,8 @@ #include <core.h> #include <test-api.h> #include <Ice/ObjectAdapter.h> +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/classification.hpp> using namespace UserIceSpider; @@ -40,14 +42,18 @@ class TestRequest : public IceSpider::IHttpRequest { public: TestRequest(const IceSpider::Core * c, HttpMethod m, const std::string & p) : IHttpRequest(c), - method(m), - path(p) + method(m) { + namespace ba = boost::algorithm; + auto path = p.substr(1); + if (!path.empty()) { + ba::split(url, path, ba::is_any_of("/"), ba::token_compress_off); + } } - std::string getRequestPath() const override + const std::vector<std::string> & getRequestPath() const override { - return path; + return url; } HttpMethod getRequestMethod() const override @@ -55,11 +61,6 @@ class TestRequest : public IceSpider::IHttpRequest { return method; } - IceUtil::Optional<std::string> getURLParam(const std::string & key) const override - { - return AdHoc::safeMapLookup<std::runtime_error>(url, key); - } - IceUtil::Optional<std::string> getQueryStringParam(const std::string & key) const override { return AdHoc::safeMapLookup<std::runtime_error>(qs, key); @@ -81,14 +82,14 @@ class TestRequest : public IceSpider::IHttpRequest { } typedef std::map<std::string, std::string> MapVars; - MapVars url; + typedef std::vector<std::string> UrlVars; + UrlVars url; MapVars qs; MapVars hdr; mutable std::stringstream input; mutable std::stringstream output; const HttpMethod method; - const std::string path; }; BOOST_AUTO_TEST_CASE( testFindRoutes ) @@ -168,29 +169,22 @@ BOOST_AUTO_TEST_CASE( testCallMethods ) BOOST_REQUIRE_EQUAL(requestGetIndex.output.str(), "200 OK\r\n\r\n{\"value\":\"index\"}"); TestRequest requestGetItem(this, HttpMethod::GET, "/view/something/1234"); - requestGetItem.url["s"] = "something"; - requestGetItem.url["i"] = "1234"; process(&requestGetItem); BOOST_REQUIRE_EQUAL(requestGetItem.output.str(), "200 OK\r\n\r\n{\"value\":\"withParams\"}"); TestRequest requestGetItemGiven(this, HttpMethod::GET, "/item/something/1234"); - requestGetItemGiven.url["s"] = "something"; - requestGetItemGiven.url["i"] = "1234"; process(&requestGetItemGiven); BOOST_REQUIRE_EQUAL(requestGetItemGiven.output.str(), "200 OK\r\n\r\n{\"value\":\"withParams\"}"); TestRequest requestGetItemDefault(this, HttpMethod::GET, "/item/something"); - requestGetItemDefault.url["s"] = "something"; process(&requestGetItemDefault); BOOST_REQUIRE_EQUAL(requestGetItemDefault.output.str(), "200 OK\r\n\r\n{\"value\":\"withParams\"}"); TestRequest requestDeleteItem(this, HttpMethod::DELETE, "/some value"); - requestDeleteItem.url["s"] = "some value"; process(&requestDeleteItem); BOOST_REQUIRE_EQUAL(requestDeleteItem.output.str(), "200 OK\r\n\r\n"); TestRequest requestUpdateItem(this, HttpMethod::POST, "/1234"); - requestUpdateItem.url["id"] = "1234"; requestUpdateItem.hdr["Content-Type"] = "application/json"; requestUpdateItem.input << "{\"value\": \"some value\"}"; process(&requestUpdateItem); |