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); | 
