From 8c88dc924cfb6119a48cdff3b3e2613131ddf974 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 17 Sep 2016 01:14:15 +0100 Subject: Proper exceptions for handling 404 and 405 --- icespider/common/http.ice | 5 +++++ icespider/core/core.cpp | 27 ++++++++++++++++----------- icespider/core/core.h | 15 +++++++++++++++ icespider/unittests/testApp.cpp | 22 ++++++++++++++++------ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/icespider/common/http.ice b/icespider/common/http.ice index cefb494..abf235f 100644 --- a/icespider/common/http.ice +++ b/icespider/common/http.ice @@ -2,6 +2,11 @@ #define ICESPIDER_HTTP_ICE module IceSpider { + exception HttpException { + int code; + string message; + }; + enum HttpMethod { GET, HEAD, POST, PUT, DELETE, OPTIONS }; diff --git a/icespider/core/core.cpp b/icespider/core/core.cpp index da6a53d..211a4da 100644 --- a/icespider/core/core.cpp +++ b/icespider/core/core.cpp @@ -5,6 +5,9 @@ namespace IceSpider { const boost::filesystem::path Core::defaultConfig("config/ice.properties"); + DefineHttpEx(Http404_NotFound, 404, "Not found"); + DefineHttpEx(Http405_MethodNotAllowed, 405, "Method Not Allowed"); + static bool operator/=(const PathElements & pathparts, const IRouteHandler * r) @@ -49,12 +52,17 @@ namespace IceSpider { void Core::process(IHttpRequest * request) const { - auto routeHandler = findRoute(request); - if (routeHandler) { - routeHandler->execute(request); + try { + findRoute(request)->execute(request); + } + catch (const HttpException & he) { + request->response(he.code, he.message); + } + catch (const std::exception & e) { + request->response(500, e.what()); } - else { - request->response(404, "Not found"); + catch (...) { + request->response(500, "Unknown internal server error"); } } @@ -63,8 +71,7 @@ namespace IceSpider { { const auto & pathparts = request->getRequestPath(); if (pathparts.size() >= routes.size()) { - // Not found error - return NULL; + throw Http404_NotFound(); } const auto & routeSet = routes[pathparts.size()]; bool match = false; @@ -77,11 +84,9 @@ namespace IceSpider { } } if (!match) { - // Not found error - return NULL; + throw Http404_NotFound(); } - // Method not allowed - return NULL; + throw Http405_MethodNotAllowed(); } Ice::ObjectPrx diff --git a/icespider/core/core.h b/icespider/core/core.h index 77d338e..9b011a5 100644 --- a/icespider/core/core.h +++ b/icespider/core/core.h @@ -7,7 +7,22 @@ #include #include +#define DeclareHttpEx(Name) \ + class Name : public ::IceSpider::HttpException { \ + public: \ + Name(); \ + static const int code; \ + static const std::string message; \ + } +#define DefineHttpEx(Name, Code, Message) \ + Name::Name() : ::IceSpider::HttpException(code, message) { } \ + const int Name::code(Code); \ + const std::string Name::message(Message); + namespace IceSpider { + DeclareHttpEx(Http404_NotFound); + DeclareHttpEx(Http405_MethodNotAllowed); + class DLL_PUBLIC Core { public: typedef std::vector LengthRoutes; diff --git a/icespider/unittests/testApp.cpp b/icespider/unittests/testApp.cpp index 0c44f5e..2a584a4 100644 --- a/icespider/unittests/testApp.cpp +++ b/icespider/unittests/testApp.cpp @@ -101,13 +101,13 @@ BOOST_AUTO_TEST_CASE( testFindRoutes ) BOOST_REQUIRE(findRoute(&requestGetIndex)); TestRequest requestPostIndex(this, HttpMethod::POST, "/"); - BOOST_REQUIRE(!findRoute(&requestPostIndex)); + BOOST_REQUIRE_THROW(findRoute(&requestPostIndex), IceSpider::Http405_MethodNotAllowed); TestRequest requestPostUpdate(this, HttpMethod::POST, "/something"); BOOST_REQUIRE(findRoute(&requestPostUpdate)); TestRequest requestGetUpdate(this, HttpMethod::GET, "/something"); - BOOST_REQUIRE(!findRoute(&requestGetUpdate)); + BOOST_REQUIRE_THROW(findRoute(&requestGetUpdate), IceSpider::Http405_MethodNotAllowed); TestRequest requestGetItem(this, HttpMethod::GET, "/view/something/something"); BOOST_REQUIRE(findRoute(&requestGetItem)); @@ -119,13 +119,13 @@ BOOST_AUTO_TEST_CASE( testFindRoutes ) BOOST_REQUIRE(findRoute(&requestGetItemDefault)); TestRequest requestGetItemLong(this, HttpMethod::GET, "/view/something/something/extra"); - BOOST_REQUIRE(!findRoute(&requestGetItemLong)); + BOOST_REQUIRE_THROW(findRoute(&requestGetItemLong), IceSpider::Http404_NotFound); TestRequest requestGetItemShort(this, HttpMethod::GET, "/view/missingSomething"); - BOOST_REQUIRE(!findRoute(&requestGetItemShort)); + BOOST_REQUIRE_THROW(findRoute(&requestGetItemShort), IceSpider::Http404_NotFound); TestRequest requestGetNothing(this, HttpMethod::GET, "/badview/something/something"); - BOOST_REQUIRE(!findRoute(&requestGetNothing)); + BOOST_REQUIRE_THROW(findRoute(&requestGetNothing), IceSpider::Http404_NotFound); TestRequest requestDeleteThing(this, HttpMethod::DELETE, "/something"); BOOST_REQUIRE(findRoute(&requestDeleteThing)); @@ -388,7 +388,7 @@ BOOST_AUTO_TEST_CASE( testCallIndexComplexAccept ) BOOST_AUTO_TEST_CASE( testCall404 ) { - TestRequest requestGetIndex(this, HttpMethod::GET, "/404"); + TestRequest requestGetIndex(this, HttpMethod::GET, "/this/404"); process(&requestGetIndex); auto h = parseHeaders(requestGetIndex.output); BOOST_REQUIRE_EQUAL(h["Status"], "404 Not found"); @@ -396,5 +396,15 @@ BOOST_AUTO_TEST_CASE( testCall404 ) BOOST_REQUIRE(requestGetIndex.output.eof()); } +BOOST_AUTO_TEST_CASE( testCall405 ) +{ + TestRequest requestGetIndex(this, HttpMethod::GET, "/405"); + process(&requestGetIndex); + auto h = parseHeaders(requestGetIndex.output); + BOOST_REQUIRE_EQUAL(h["Status"], "405 Method Not Allowed"); + requestGetIndex.output.get(); + BOOST_REQUIRE(requestGetIndex.output.eof()); +} + BOOST_AUTO_TEST_SUITE_END(); -- cgit v1.2.3