summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-06-26 12:40:30 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2016-06-26 12:40:30 +0100
commite548772e83997fd2b1cdf1473b68e912ee986018 (patch)
tree2aef1b314709d88585dd8f225a62e27259743cc9
parentDefault parameter expressions (diff)
downloadicespider-e548772e83997fd2b1cdf1473b68e912ee986018.tar.bz2
icespider-e548772e83997fd2b1cdf1473b68e912ee986018.tar.xz
icespider-e548772e83997fd2b1cdf1473b68e912ee986018.zip
URL parameters by index internally, not key
-rw-r--r--icespider/compile/routeCompiler.cpp31
-rw-r--r--icespider/core/core.cpp10
-rw-r--r--icespider/core/ihttpRequest.cpp18
-rw-r--r--icespider/core/ihttpRequest.h6
-rw-r--r--icespider/core/irouteHandler.h8
-rw-r--r--icespider/fcgi/cgiRequestBase.cpp22
-rw-r--r--icespider/fcgi/cgiRequestBase.h6
-rw-r--r--icespider/unittests/testApp.cpp30
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);