summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-09-17 03:04:57 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2016-09-17 03:04:57 +0100
commita3b011c92111c144cdbc726a6e1458ca25eb807f (patch)
tree23774105b6b3d633060cc89a112afdbd22344df1
parentMove exceptions to their own files (diff)
downloadicespider-a3b011c92111c144cdbc726a6e1458ca25eb807f.tar.bz2
icespider-a3b011c92111c144cdbc726a6e1458ca25eb807f.tar.xz
icespider-a3b011c92111c144cdbc726a6e1458ca25eb807f.zip
Bad request on missing or invalid parameters
-rw-r--r--icespider/core/ihttpRequest.cpp15
-rw-r--r--icespider/core/irouteHandler.cpp6
-rw-r--r--icespider/core/irouteHandler.h9
-rw-r--r--icespider/unittests/testApp.cpp51
-rw-r--r--icespider/unittests/testCompile.cpp4
-rw-r--r--icespider/unittests/testRoutes.json16
6 files changed, 91 insertions, 10 deletions
diff --git a/icespider/core/ihttpRequest.cpp b/icespider/core/ihttpRequest.cpp
index d9abecd..ea2c0bd 100644
--- a/icespider/core/ihttpRequest.cpp
+++ b/icespider/core/ihttpRequest.cpp
@@ -82,10 +82,21 @@ namespace IceSpider {
return url[idx];
}
+ template <typename T, typename Y>
+ inline T wrapLexicalCast(const Y & y)
+ {
+ try {
+ return boost::lexical_cast<T>(y);
+ }
+ catch (const boost::bad_lexical_cast &) {
+ throw Http400_BadRequest();
+ }
+ }
+
template <typename T>
inline IceUtil::Optional<T> optionalLexicalCast(const IceUtil::Optional<std::string> & p)
{
- if (p) return boost::lexical_cast<T>(*p);
+ if (p) return wrapLexicalCast<T>(*p);
return IceUtil::Optional<T>();
}
@@ -99,7 +110,7 @@ namespace IceSpider {
#define getParams(T) \
template<> T IHttpRequest::getURLParam<T>(unsigned int idx) const { \
- return boost::lexical_cast<T>(getURLParam(idx)); } \
+ return wrapLexicalCast<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 { \
diff --git a/icespider/core/irouteHandler.cpp b/icespider/core/irouteHandler.cpp
index 9d33a6b..6681697 100644
--- a/icespider/core/irouteHandler.cpp
+++ b/icespider/core/irouteHandler.cpp
@@ -41,6 +41,12 @@ namespace IceSpider {
}
void
+ IRouteHandler::requiredParameterNotFound(const char *, const std::string &) const
+ {
+ throw Http400_BadRequest();
+ }
+
+ void
IRouteHandler::addRouteSerializer(const MimeType & ct, StreamSerializerFactoryPtr ssfp)
{
routeSerializers.erase(ct);
diff --git a/icespider/core/irouteHandler.h b/icespider/core/irouteHandler.h
index e75ec8f..595ea95 100644
--- a/icespider/core/irouteHandler.h
+++ b/icespider/core/irouteHandler.h
@@ -3,6 +3,7 @@
#include "ihttpRequest.h"
#include "util.h"
+#include "exceptions.h"
#include <pathparts.h>
#include <routes.h>
#include <factory.h>
@@ -28,11 +29,13 @@ namespace IceSpider {
typedef std::map<MimeType, StreamSerializerFactoryPtr> RouteSerializers;
RouteSerializers routeSerializers;
+ void requiredParameterNotFound(const char *, const std::string & key) const;
+
template <typename T, typename K>
- inline T requiredParameterNotFound(const char *, const K & key) const
+ inline T requiredParameterNotFound(const char * s, const K & key) const
{
- throw std::runtime_error("Required parameter not found: " +
- boost::lexical_cast<std::string>(key));
+ requiredParameterNotFound(s, key);
+ return T();
}
void addRouteSerializer(const MimeType &, StreamSerializerFactoryPtr);
diff --git a/icespider/unittests/testApp.cpp b/icespider/unittests/testApp.cpp
index 80cecda..0806542 100644
--- a/icespider/unittests/testApp.cpp
+++ b/icespider/unittests/testApp.cpp
@@ -27,7 +27,7 @@ void forceEarlyChangeDir()
BOOST_AUTO_TEST_CASE( testLoadConfiguration )
{
- BOOST_REQUIRE_EQUAL(9, AdHoc::PluginManager::getDefault()->getAll<IceSpider::RouteHandlerFactory>().size());
+ BOOST_REQUIRE_EQUAL(10, AdHoc::PluginManager::getDefault()->getAll<IceSpider::RouteHandlerFactory>().size());
}
class TestRequest : public IHttpRequest {
@@ -55,7 +55,7 @@ class TestRequest : public IHttpRequest {
IceUtil::Optional<std::string> getQueryStringParam(const std::string & key) const override
{
- return AdHoc::safeMapLookup<std::runtime_error>(qs, key);
+ return qs.find(key) == qs.end() ? IceUtil::Optional<std::string>() : qs.find(key)->second;
}
IceUtil::Optional<std::string> getHeaderParam(const std::string & key) const override
@@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE( testCoreSettings )
{
BOOST_REQUIRE_EQUAL(5, routes.size());
BOOST_REQUIRE_EQUAL(1, routes[0].size());
- BOOST_REQUIRE_EQUAL(3, routes[1].size());
+ BOOST_REQUIRE_EQUAL(4, routes[1].size());
BOOST_REQUIRE_EQUAL(1, routes[2].size());
BOOST_REQUIRE_EQUAL(2, routes[3].size());
BOOST_REQUIRE_EQUAL(2, routes[4].size());
@@ -430,5 +430,50 @@ BOOST_AUTO_TEST_CASE( testCall405 )
BOOST_REQUIRE(requestGetIndex.output.eof());
}
+BOOST_AUTO_TEST_CASE( testCallSearch )
+{
+ TestRequest request(this, HttpMethod::GET, "/search");
+ request.qs["s"] = "something";
+ request.qs["i"] = "1234";
+ process(&request);
+ auto h = parseHeaders(request.output);
+ BOOST_REQUIRE_EQUAL(h["Status"], "200 OK");
+ Slicer::DeserializeAny<Slicer::JsonStreamDeserializer, TestIceSpider::SomeModelPtr>(request.output);
+}
+
+BOOST_AUTO_TEST_CASE( testCallSearchBadLexicalCast )
+{
+ TestRequest request(this, HttpMethod::GET, "/search");
+ request.qs["s"] = "something";
+ request.qs["i"] = "bar";
+ process(&request);
+ auto h = parseHeaders(request.output);
+ BOOST_REQUIRE_EQUAL(h["Status"], "400 Bad Request");
+ request.output.get();
+ BOOST_REQUIRE(request.output.eof());
+}
+
+BOOST_AUTO_TEST_CASE( testCallSearchMissingS )
+{
+ TestRequest request(this, HttpMethod::GET, "/search");
+ request.qs["i"] = "1234";
+ process(&request);
+ auto h = parseHeaders(request.output);
+ BOOST_REQUIRE_EQUAL(h["Status"], "400 Bad Request");
+ request.output.get();
+ BOOST_REQUIRE(request.output.eof());
+}
+
+BOOST_AUTO_TEST_CASE( testCallSearchMissingI )
+{
+ TestRequest request(this, HttpMethod::GET, "/search");
+ request.qs["s"] = "something";
+ process(&request);
+ auto h = parseHeaders(request.output);
+ BOOST_REQUIRE_EQUAL(h["Status"], "400 Bad Request");
+ request.output.get();
+ BOOST_REQUIRE(request.output.eof());
+}
+
BOOST_AUTO_TEST_SUITE_END();
diff --git a/icespider/unittests/testCompile.cpp b/icespider/unittests/testCompile.cpp
index 425821f..063d691 100644
--- a/icespider/unittests/testCompile.cpp
+++ b/icespider/unittests/testCompile.cpp
@@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE( testLoadConfiguration )
rc.applyDefaults(cfg, u);
BOOST_REQUIRE_EQUAL("common", cfg->name);
- BOOST_REQUIRE_EQUAL(9, cfg->routes.size());
+ BOOST_REQUIRE_EQUAL(10, cfg->routes.size());
BOOST_REQUIRE_EQUAL("index", cfg->routes[0]->name);
BOOST_REQUIRE_EQUAL("/", cfg->routes[0]->path);
@@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE( testLoad )
BOOST_TEST_INFO(dlerror());
BOOST_REQUIRE(lib);
- BOOST_REQUIRE_EQUAL(9, AdHoc::PluginManager::getDefault()->getAll<IceSpider::RouteHandlerFactory>().size());
+ BOOST_REQUIRE_EQUAL(10, AdHoc::PluginManager::getDefault()->getAll<IceSpider::RouteHandlerFactory>().size());
// smoke test (block ensure dlclose dones't cause segfault)
{
auto route = AdHoc::PluginManager::getDefault()->get<IceSpider::RouteHandlerFactory>("common::index");
diff --git a/icespider/unittests/testRoutes.json b/icespider/unittests/testRoutes.json
index d2d713a..daf090d 100644
--- a/icespider/unittests/testRoutes.json
+++ b/icespider/unittests/testRoutes.json
@@ -115,6 +115,22 @@
}
],
"operation": "TestIceSpider.TestApi.index"
+ },
+ {
+ "name": "search",
+ "path": "/search",
+ "method": "GET",
+ "operation": "TestIceSpider.TestApi.withParams",
+ "params": [
+ {
+ "name": "s",
+ "source": "QueryString"
+ },
+ {
+ "name": "i",
+ "source": "QueryString"
+ }
+ ]
}
],
"slices": [