summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--icespider/common/routes.ice1
-rw-r--r--icespider/compile/routeCompiler.cpp10
-rw-r--r--icespider/core/ihttpRequest.cpp30
-rw-r--r--icespider/core/ihttpRequest.h15
-rw-r--r--icespider/core/irouteHandler.h7
-rw-r--r--icespider/core/util.h16
-rw-r--r--icespider/unittests/test-api.ice2
-rw-r--r--icespider/unittests/testApp.cpp11
-rw-r--r--icespider/unittests/testRoutes.json3
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",