diff options
-rw-r--r-- | icespider/core/ihttpRequest.cpp | 15 | ||||
-rw-r--r-- | icespider/core/irouteHandler.cpp | 6 | ||||
-rw-r--r-- | icespider/core/irouteHandler.h | 9 | ||||
-rw-r--r-- | icespider/unittests/testApp.cpp | 51 | ||||
-rw-r--r-- | icespider/unittests/testCompile.cpp | 4 | ||||
-rw-r--r-- | icespider/unittests/testRoutes.json | 16 |
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": [ |