diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-06-20 22:47:55 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-06-20 22:47:55 +0100 | 
| commit | ec1c32942c311c221520d31dcb92803ab769294f (patch) | |
| tree | efce5876c08f65954b3d70e5dfe8665e2f536d9d | |
| parent | Compat fix (diff) | |
| download | icespider-ec1c32942c311c221520d31dcb92803ab769294f.tar.bz2 icespider-ec1c32942c311c221520d31dcb92803ab769294f.tar.xz icespider-ec1c32942c311c221520d31dcb92803ab769294f.zip | |
Parameters can be optional
| -rw-r--r-- | icespider/common/routes.ice | 1 | ||||
| -rw-r--r-- | icespider/compile/routeCompiler.cpp | 10 | ||||
| -rw-r--r-- | icespider/core/ihttpRequest.cpp | 30 | ||||
| -rw-r--r-- | icespider/core/ihttpRequest.h | 15 | ||||
| -rw-r--r-- | icespider/core/irouteHandler.h | 7 | ||||
| -rw-r--r-- | icespider/core/util.h | 16 | ||||
| -rw-r--r-- | icespider/unittests/test-api.ice | 2 | ||||
| -rw-r--r-- | icespider/unittests/testApp.cpp | 11 | ||||
| -rw-r--r-- | icespider/unittests/testRoutes.json | 3 | 
9 files changed, 69 insertions, 26 deletions
| diff --git a/icespider/common/routes.ice b/icespider/common/routes.ice index 8f7b520..01bed51 100644 --- a/icespider/common/routes.ice +++ b/icespider/common/routes.ice @@ -9,6 +9,7 @@ module UserIceSpider {  		string name;  		ParameterSource source;  		optional(0) string key; +		bool isOptional = false;  	};  	sequence<Parameter> Parameters;  	class Route { diff --git a/icespider/compile/routeCompiler.cpp b/icespider/compile/routeCompiler.cpp index aee3f7f..9addd56 100644 --- a/icespider/compile/routeCompiler.cpp +++ b/icespider/compile/routeCompiler.cpp @@ -86,7 +86,7 @@ namespace IceSpider {  						if (!d->key) d->key = d->name;  						continue;  					} -					r->params.push_back(new UserIceSpider::Parameter(p->name(), UserIceSpider::ParameterSource::URL, p->name())); +					r->params.push_back(new UserIceSpider::Parameter(p->name(), UserIceSpider::ParameterSource::URL, p->name(), false));  				}  			}  		} @@ -222,8 +222,14 @@ namespace IceSpider {  				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));\n", +					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); +					} +					fprintbf(0, output, ");\n");  				}  				fprintbf(4, output, "auto prx = getProxy<%s>(request);\n", proxyName);  				if (o->returnsData()) { diff --git a/icespider/core/ihttpRequest.cpp b/icespider/core/ihttpRequest.cpp index de26a1c..73367ca 100644 --- a/icespider/core/ihttpRequest.cpp +++ b/icespider/core/ihttpRequest.cpp @@ -1,4 +1,5 @@  #include "ihttpRequest.h" +#include "util.h"  #include <boost/lexical_cast.hpp>  namespace IceSpider { @@ -17,7 +18,9 @@ namespace IceSpider {  	IHttpRequest::getDeserializer() const  	{  		return Slicer::StreamDeserializerFactory::createNew( -			getHeaderParam("Content-Type"), getInputStream()); +			getHeaderParam("Content-Type") / []() -> std::string { +				throw std::runtime_error("Content-Type must be specified to deserialize payload"); +			}, getInputStream());  	}  	Slicer::SerializerPtr @@ -27,18 +30,25 @@ namespace IceSpider {  			"application/json", getOutputStream());  	} +	template <typename T> +	inline IceUtil::Optional<T> optionalLexicalCast(const IceUtil::Optional<std::string> & p) +	{ +		if (p) return boost::lexical_cast<T>(*p); +		return IceUtil::Optional<T>(); +	} +  #define getParams(T) \ -	template<> T IHttpRequest::getURLParam<T>(const std::string & key) const { \ -		return boost::lexical_cast<T>(getURLParam(key)); } \ -	template<> T IHttpRequest::getQueryStringParam<T>(const std::string & key) const { \ -		return boost::lexical_cast<T>(getQueryStringParam(key)); } \ -	template<> T IHttpRequest::getHeaderParam<T>(const std::string & key) const { \ -		return boost::lexical_cast<T>(getHeaderParam(key)); } -	template<> std::string IHttpRequest::getURLParam<std::string>(const std::string & key) const { \ +	template<> IceUtil::Optional<T> IHttpRequest::getURLParam<T>(const std::string & key) const { \ +		return optionalLexicalCast<T>(getURLParam(key)); } \ +	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::getQueryStringParam<std::string>(const std::string & key) const { \ +	template<> IceUtil::Optional<std::string> IHttpRequest::getQueryStringParam<std::string>(const std::string & key) const { \  		return getQueryStringParam(key); } -	template<> std::string IHttpRequest::getHeaderParam<std::string>(const std::string & key) const { \ +	template<> IceUtil::Optional<std::string> IHttpRequest::getHeaderParam<std::string>(const std::string & key) const { \  		return getHeaderParam(key); }  	getParams(bool); diff --git a/icespider/core/ihttpRequest.h b/icespider/core/ihttpRequest.h index 6b1a3b0..da903ef 100644 --- a/icespider/core/ihttpRequest.h +++ b/icespider/core/ihttpRequest.h @@ -7,6 +7,7 @@  #include <visibility.h>  #include <routes.h>  #include <slicer/slicer.h> +#include <IceUtil/Optional.h>  namespace IceSpider {  	class Core; @@ -19,25 +20,25 @@ namespace IceSpider {  			virtual std::string getRequestPath() const = 0;  			virtual UserIceSpider::HttpMethod getRequestMethod() const = 0; -			virtual std::string getURLParam(const std::string &) const = 0; -			virtual std::string getQueryStringParam(const std::string &) const = 0; -			virtual std::string getHeaderParam(const std::string &) const = 0; +			virtual IceUtil::Optional<std::string> getURLParam(const std::string &) const = 0; +			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;  			virtual Slicer::SerializerPtr getSerializer() const;  			virtual std::istream & getInputStream() const = 0;  			virtual std::ostream & getOutputStream() const = 0;  			template<typename T> -			T getURLParam(const std::string & key) const; +			IceUtil::Optional<T> getURLParam(const std::string & key) const;  			template<typename T> -			T getBodyParam(const std::string &) const +			IceUtil::Optional<T> getBodyParam(const std::string &) const  			{  				return Slicer::DeserializeAnyWith<T>(getDeserializer());  			}  			template<typename T> -			T getQueryStringParam(const std::string & key) const; +			IceUtil::Optional<T> getQueryStringParam(const std::string & key) const;  			template<typename T> -			T getHeaderParam(const std::string & key) const; +			IceUtil::Optional<T> getHeaderParam(const std::string & key) const;  			template<typename T>  			void response(const T & t) const  			{ diff --git a/icespider/core/irouteHandler.h b/icespider/core/irouteHandler.h index 416048e..911c1b4 100644 --- a/icespider/core/irouteHandler.h +++ b/icespider/core/irouteHandler.h @@ -2,6 +2,7 @@  #define ICESPIDER_IROUTEHANDLER_H  #include "ihttpRequest.h" +#include "util.h"  #include "paths.h"  #include <routes.h>  #include <plugins.h> @@ -16,6 +17,12 @@ namespace IceSpider {  			const UserIceSpider::HttpMethod method;  		protected: +			template <typename T> +			inline T requiredParameterNotFound(const char *, const std::string & key) const +			{ +				throw std::runtime_error("Required parameter not found: " + key); +			} +  			Ice::ObjectPrx getProxy(IHttpRequest *, const char *) const;  			template<typename Interface> diff --git a/icespider/core/util.h b/icespider/core/util.h new file mode 100644 index 0000000..638660c --- /dev/null +++ b/icespider/core/util.h @@ -0,0 +1,16 @@ +#ifndef ICESPIDER_CORE_UTIL_H +#define ICESPIDER_CORE_UTIL_H + +#include <IceUtil/Optional.h> + +namespace IceUtil { +	template <typename T, typename TF> +	T operator/(const IceUtil::Optional<T> & o, const TF & tf) +	{ +		if (o) return *o; +		return tf(); +	} +} + +#endif + diff --git a/icespider/unittests/test-api.ice b/icespider/unittests/test-api.ice index 4fc87bd..ff43dc2 100644 --- a/icespider/unittests/test-api.ice +++ b/icespider/unittests/test-api.ice @@ -7,7 +7,7 @@ module TestIceSpider {  		SomeModel index();	  		SomeModel withParams(string s, int i);  		void returnNothing(string s); -		void complexParam(string s, SomeModel m); +		void complexParam(optional(0) string s, SomeModel m);  	};  }; diff --git a/icespider/unittests/testApp.cpp b/icespider/unittests/testApp.cpp index aa00c43..e91f618 100644 --- a/icespider/unittests/testApp.cpp +++ b/icespider/unittests/testApp.cpp @@ -55,17 +55,17 @@ class TestRequest : public IceSpider::IHttpRequest {  			return method;  		} -		std::string getURLParam(const std::string & key) const override +		IceUtil::Optional<std::string> getURLParam(const std::string & key) const override  		{  			return AdHoc::safeMapLookup<std::runtime_error>(url, key);  		} -		std::string getQueryStringParam(const std::string & key) const override +		IceUtil::Optional<std::string> getQueryStringParam(const std::string & key) const override  		{  			return AdHoc::safeMapLookup<std::runtime_error>(qs, key);  		} -		std::string getHeaderParam(const std::string & key) const override +		IceUtil::Optional<std::string> getHeaderParam(const std::string & key) const override  		{  			return AdHoc::safeMapLookup<std::runtime_error>(hdr, key);  		} @@ -140,9 +140,10 @@ class TestSerice : public TestIceSpider::TestApi {  			BOOST_REQUIRE_EQUAL(s, "some value");  		} -		void complexParam(const std::string & s, const TestIceSpider::SomeModelPtr & m, const Ice::Current &) override +		void complexParam(const IceUtil::Optional<std::string> & s, const TestIceSpider::SomeModelPtr & m, const Ice::Current &) override  		{ -			BOOST_REQUIRE_EQUAL(s, "1234"); +			BOOST_REQUIRE(s); +			BOOST_REQUIRE_EQUAL("1234", *s);  			BOOST_REQUIRE(m);  			BOOST_REQUIRE_EQUAL("some value", m->value);  		} diff --git a/icespider/unittests/testRoutes.json b/icespider/unittests/testRoutes.json index 2b7b48d..b766f31 100644 --- a/icespider/unittests/testRoutes.json +++ b/icespider/unittests/testRoutes.json @@ -28,7 +28,8 @@  		{  			"name": "s",  			"source": "URL", -			"key": "id" +			"key": "id", +			"isOptional": true  		},  		{  			"name": "m", | 
