diff options
| -rw-r--r-- | icespider/common/Jamfile.jam | 4 | ||||
| -rw-r--r-- | icespider/common/pathparts.cpp (renamed from icespider/core/paths.cpp) | 10 | ||||
| -rw-r--r-- | icespider/common/pathparts.h (renamed from icespider/core/paths.h) | 16 | ||||
| -rw-r--r-- | icespider/common/routes.ice | 9 | ||||
| -rw-r--r-- | icespider/compile/routeCompiler.cpp | 72 | ||||
| -rw-r--r-- | icespider/core/core.cpp | 2 | ||||
| -rw-r--r-- | icespider/core/irouteHandler.h | 2 | ||||
| -rw-r--r-- | icespider/unittests/testApp.cpp | 25 | ||||
| -rw-r--r-- | icespider/unittests/testCompile.cpp | 4 | ||||
| -rw-r--r-- | icespider/unittests/testRoutes.json | 24 | 
10 files changed, 136 insertions, 32 deletions
| diff --git a/icespider/common/Jamfile.jam b/icespider/common/Jamfile.jam index 081ebd1..c06ff0c 100644 --- a/icespider/common/Jamfile.jam +++ b/icespider/common/Jamfile.jam @@ -1,6 +1,9 @@ +lib adhocutil : : : : <include>/usr/include/adhocutil ; +  lib icespider-common :  	[ glob-tree *.ice *.cpp : bin ]  	: +	<library>adhocutil  	<library>..//pthread  	<library>..//Ice  	<library>..//IceUtil @@ -8,5 +11,6 @@ lib icespider-common :  	<library>..//pthread  	<library>..//Ice  	<library>..//IceUtil +	<include>.  	; diff --git a/icespider/core/paths.cpp b/icespider/common/pathparts.cpp index f4bad0e..d7581b3 100644 --- a/icespider/core/paths.cpp +++ b/icespider/common/pathparts.cpp @@ -1,5 +1,6 @@ -#include "paths.h" +#include "pathparts.h"  #include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/trim.hpp>  namespace ba = boost::algorithm; @@ -12,7 +13,7 @@ namespace IceSpider {  		for (auto pi = ba::make_split_iterator(relp, ba::first_finder("/", ba::is_equal())); pi != decltype(pi)(); ++pi) {  			std::string pp(pi->begin(), pi->end());  			if (pp.front() == '{' && pp.back() == '}') { -				parts.push_back(PathPartPtr(new PathParameter())); +				parts.push_back(PathPartPtr(new PathParameter(pp)));  			}  			else {  				parts.push_back(PathPartPtr(new PathLiteral(pp))); @@ -38,6 +39,11 @@ namespace IceSpider {  		return value == v;  	} +	PathParameter::PathParameter(const std::string & s) : +		name(boost::algorithm::trim_copy_if(s, ispunct)) +	{ +	} +  	bool  	PathParameter::matches(const std::string &) const  	{ diff --git a/icespider/core/paths.h b/icespider/common/pathparts.h index 0999593..0720af0 100644 --- a/icespider/core/paths.h +++ b/icespider/common/pathparts.h @@ -4,30 +4,34 @@  #include <vector>  #include <string>  #include <memory> +#include <visibility.h>  namespace IceSpider { - -	class PathPart { +	class DLL_PUBLIC PathPart {  		public:  			virtual bool matches(const std::string &) const = 0;  	};  	typedef std::shared_ptr<PathPart> PathPartPtr; -	class PathLiteral : public PathPart { +	class DLL_PUBLIC PathLiteral : public PathPart {  		public:  			PathLiteral(const std::string & v);  			bool matches(const std::string &) const; -		private:  			const std::string value;  	}; -	class PathParameter : public PathPart { +	class DLL_PUBLIC PathParameter : public PathPart {  		public: +			PathParameter(const std::string &); +  			bool matches(const std::string &) const; + +			const std::string name;  	}; -	class Path { + +	class DLL_PUBLIC Path {  		public:  			typedef std::vector<PathPartPtr> PathParts; diff --git a/icespider/common/routes.ice b/icespider/common/routes.ice index 01bed51..0e64692 100644 --- a/icespider/common/routes.ice +++ b/icespider/common/routes.ice @@ -7,15 +7,20 @@ module UserIceSpider {  	};  	class Parameter {  		string name; -		ParameterSource source; +		ParameterSource source = URL;  		optional(0) string key;  		bool isOptional = false; +		["slicer:name:default"] +		optional(1) string defaultExpr; + +		["slicer:ignore"] +		bool hasUserSource;  	};  	sequence<Parameter> Parameters;  	class Route {  		string name;  		string path; -		HttpMethod method; +		HttpMethod method = GET;  		string operation;  		Parameters params;  	}; diff --git a/icespider/compile/routeCompiler.cpp b/icespider/compile/routeCompiler.cpp index 9c6c59d..b28231e 100644 --- a/icespider/compile/routeCompiler.cpp +++ b/icespider/compile/routeCompiler.cpp @@ -1,4 +1,5 @@  #include "routeCompiler.h" +#include <pathparts.h>  #include <slicer/slicer.h>  #include <slicer/modelPartsTypes.h>  #include <Slice/Preprocessor.h> @@ -84,9 +85,21 @@ namespace IceSpider {  					if (defined != r->params.end()) {  						auto d = *defined;  						if (!d->key) d->key = d->name; -						continue;  					} -					r->params.push_back(new UserIceSpider::Parameter(p->name(), UserIceSpider::ParameterSource::URL, p->name(), false)); +					else { +						r->params.push_back(new UserIceSpider::Parameter(p->name(), UserIceSpider::ParameterSource::URL, p->name(), false, IceUtil::Optional<std::string>(), false)); +						defined = --r->params.end(); +					} +					auto d = *defined; +					if (d->source == UserIceSpider::ParameterSource::URL) { +						IceSpider::Path path(r->path); +						d->hasUserSource = std::find_if(path.parts.begin(), path.parts.end(), [d](const auto & pp) { +							if (auto par = dynamic_cast<PathParameter *>(pp.get())) { +								return par->name == d->key; +							} +							return false; +						}) != path.parts.end(); +					}  				}  			}  		} @@ -211,8 +224,15 @@ namespace IceSpider {  				fprintbf(3, output, "%s() :\n", r->name);  				fprintbf(4, output, "IceSpider::IRouteHandler(UserIceSpider::HttpMethod::%s, \"%s\")", methodName, r->path);  				for (const auto & p : r->params) { -					fprintf(output, ",\n"); -					fprintbf(4, output, "_pn_%s(\"%s\")", p->name, *p->key); +					if (p->hasUserSource) { +						fprintf(output, ",\n"); +						fprintbf(4, output, "_pn_%s(\"%s\")", p->name, *p->key); +					} +					if (p->defaultExpr) { +						fprintf(output, ",\n"); +						fprintbf(4, output, "_pd_%s(%s)", +								p->name, p->defaultExpr.get()); +					}  				}  				fprintf(output, "\n");  				fprintbf(3, output, "{\n"); @@ -221,15 +241,23 @@ namespace IceSpider {  				fprintbf(3, output, "{\n");  				auto o = findOperation(r, units);  				for (const auto & p : r->params) { -					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(0, output, " /\n"); -						fprintbf(5, output, " [this]() { return requiredParameterNotFound<%s>(\"%s\", _pn_%s); }", -								Slice::typeToString(ip->type()), getEnumString(p->source), p->name); +					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(0, output, " /\n"); +							if (p->defaultExpr) { +								fprintbf(5, output, " [this]() { return _pd_%s; }", +												 p->name); +							} +							else { +								fprintbf(5, output, " [this]() { return requiredParameterNotFound<%s>(\"%s\", _pn_%s); }", +												 Slice::typeToString(ip->type()), getEnumString(p->source), p->name); +							} +						} +						fprintbf(0, output, ");\n");  					} -					fprintbf(0, output, ");\n");  				}  				fprintbf(4, output, "auto prx = getProxy<%s>(request);\n", proxyName);  				if (o->returnsData()) { @@ -239,7 +267,15 @@ namespace IceSpider {  					fprintbf(4, output, "prx->%s(", operation);  				}  				for (const auto & p : o->parameters()) { -					fprintbf(output, "_p_%s, ", p->name()); +					auto rp = *std::find_if(r->params.begin(), r->params.end(), [p](const auto & rp) { +						return rp->name == p->name(); +					}); +					if (rp->hasUserSource) { +						fprintbf(output, "_p_%s, ", p->name()); +					} +					else { +						fprintbf(output, "_pd_%s, ", p->name()); +					}  				}  				fprintbf(output, "request->getContext())");  				if (o->returnsData()) { @@ -252,7 +288,15 @@ namespace IceSpider {  				fprintbf(3, output, "}\n\n");  				fprintbf(2, output, "private:\n");  				for (const auto & p : r->params) { -					fprintbf(3, output, "const std::string _pn_%s;\n", p->name); +					if (p->hasUserSource) { +						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; }); +						fprintbf(3, output, "const %s _pd_%s;\n", +								Slice::typeToString(ip->type()), p->name); + +					}  				}  				fprintbf(1, output, "};\n\n");  			} diff --git a/icespider/core/core.cpp b/icespider/core/core.cpp index 9f87bda..5509580 100644 --- a/icespider/core/core.cpp +++ b/icespider/core/core.cpp @@ -51,7 +51,7 @@ namespace IceSpider {  		if (!path.empty()) {  			ba::split(pathparts, path, ba::is_any_of("/"), ba::token_compress_off);  		} -		if (pathparts.size() > mroutes.size()) { +		if (pathparts.size() >= mroutes.size()) {  			// Not found error  			return NULL;  		} diff --git a/icespider/core/irouteHandler.h b/icespider/core/irouteHandler.h index 911c1b4..32513ae 100644 --- a/icespider/core/irouteHandler.h +++ b/icespider/core/irouteHandler.h @@ -3,7 +3,7 @@  #include "ihttpRequest.h"  #include "util.h" -#include "paths.h" +#include <pathparts.h>  #include <routes.h>  #include <plugins.h>  #include <visibility.h> diff --git a/icespider/unittests/testApp.cpp b/icespider/unittests/testApp.cpp index 1e9562b..b5af516 100644 --- a/icespider/unittests/testApp.cpp +++ b/icespider/unittests/testApp.cpp @@ -12,7 +12,7 @@ using namespace UserIceSpider;  BOOST_AUTO_TEST_CASE( testLoadConfiguration )  { -	BOOST_REQUIRE_EQUAL(4, AdHoc::PluginManager::getDefault()->getAll<IceSpider::IRouteHandler>().size()); +	BOOST_REQUIRE_EQUAL(6, AdHoc::PluginManager::getDefault()->getAll<IceSpider::IRouteHandler>().size());  }  BOOST_FIXTURE_TEST_SUITE(c, IceSpider::Core); @@ -23,8 +23,8 @@ BOOST_AUTO_TEST_CASE( testCoreSettings )  	BOOST_REQUIRE_EQUAL(4, routes[HttpMethod::GET].size());  	BOOST_REQUIRE_EQUAL(1, routes[HttpMethod::GET][0].size());  	BOOST_REQUIRE_EQUAL(0, routes[HttpMethod::GET][1].size()); -	BOOST_REQUIRE_EQUAL(0, routes[HttpMethod::GET][2].size()); -	BOOST_REQUIRE_EQUAL(1, routes[HttpMethod::GET][3].size()); +	BOOST_REQUIRE_EQUAL(1, routes[HttpMethod::GET][2].size()); +	BOOST_REQUIRE_EQUAL(2, routes[HttpMethod::GET][3].size());  	BOOST_REQUIRE_EQUAL(1, routes[HttpMethod::HEAD].size());  	BOOST_REQUIRE_EQUAL(2, routes[HttpMethod::POST].size());  	BOOST_REQUIRE_EQUAL(0, routes[HttpMethod::POST][0].size()); @@ -44,7 +44,7 @@ class TestRequest : public IceSpider::IHttpRequest {  			path(p)  		{  		} -			 +  		std::string getRequestPath() const override  		{  			return path; @@ -108,6 +108,12 @@ BOOST_AUTO_TEST_CASE( testFindRoutes )  	TestRequest requestGetItem(this, HttpMethod::GET, "/view/something/something");  	BOOST_REQUIRE(findRoute(&requestGetItem)); +	TestRequest requestGetItemParam(this, HttpMethod::GET, "/item/something/1234"); +	BOOST_REQUIRE(findRoute(&requestGetItemParam)); + +	TestRequest requestGetItemDefault(this, HttpMethod::GET, "/item/something"); +	BOOST_REQUIRE(findRoute(&requestGetItemDefault)); +  	TestRequest requestGetItemLong(this, HttpMethod::GET, "/view/something/something/extra");  	BOOST_REQUIRE(!findRoute(&requestGetItemLong)); @@ -167,6 +173,17 @@ BOOST_AUTO_TEST_CASE( testCallMethods )  	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); diff --git a/icespider/unittests/testCompile.cpp b/icespider/unittests/testCompile.cpp index 4325c16..26fc458 100644 --- a/icespider/unittests/testCompile.cpp +++ b/icespider/unittests/testCompile.cpp @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE( testLoadConfiguration )  	rc.applyDefaults(cfg, u);  	BOOST_REQUIRE_EQUAL("common", cfg->name); -	BOOST_REQUIRE_EQUAL(4, cfg->routes.size()); +	BOOST_REQUIRE_EQUAL(6, cfg->routes.size());  	BOOST_REQUIRE_EQUAL("index", cfg->routes[0]->name);  	BOOST_REQUIRE_EQUAL("/", cfg->routes[0]->path); @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE( testLoad )  	BOOST_TEST_INFO(dlerror());  	BOOST_REQUIRE(lib); -	BOOST_REQUIRE_EQUAL(4, AdHoc::PluginManager::getDefault()->getAll<IceSpider::IRouteHandler>().size()); +	BOOST_REQUIRE_EQUAL(6, AdHoc::PluginManager::getDefault()->getAll<IceSpider::IRouteHandler>().size());  	// smoke test (block ensure dlclose dones't cause segfault)  	{  		auto route = AdHoc::PluginManager::getDefault()->get<IceSpider::IRouteHandler>("common::index"); diff --git a/icespider/unittests/testRoutes.json b/icespider/unittests/testRoutes.json index b766f31..4ad8cc3 100644 --- a/icespider/unittests/testRoutes.json +++ b/icespider/unittests/testRoutes.json @@ -36,6 +36,30 @@  			"source": "Body"  		}  		] +	}, +	{ +		"name": "defaultItem", +		"path": "/item/{s}", +		"method": "GET", +		"operation": "TestIceSpider.TestApi.withParams", +		"params": [ +		{ +			"name": "i", +			"default": "1234" +		} +		] +	}, +	{ +		"name": "itemWithDefault", +		"path": "/item/{s}/{i}", +		"method": "GET", +		"operation": "TestIceSpider.TestApi.withParams", +		"params": [ +		{ +			"name": "i", +			"default": "1234" +		} +		]  	}  	],  	"slices": [ | 
