From 576690bf14c5068ebcf40cf2416ff0a8906810b6 Mon Sep 17 00:00:00 2001 From: The-EDev Date: Sat, 21 Aug 2021 04:49:17 +0300 Subject: [PATCH] Made catchall work with 404 or 405 errors snuck in a fix for release.py where version name wouldn't change also snuck in slight improvement in finding blueprint (removed extra if statement) --- examples/example_catchall.cpp | 15 +++++-- include/crow/routing.h | 74 +++++++++++++++++++---------------- scripts/release.py | 4 +- tests/unittest.cpp | 5 ++- 4 files changed, 56 insertions(+), 42 deletions(-) diff --git a/examples/example_catchall.cpp b/examples/example_catchall.cpp index 150ff3f72..522812a54 100644 --- a/examples/example_catchall.cpp +++ b/examples/example_catchall.cpp @@ -11,10 +11,17 @@ int main() //Setting a custom route for any URL that isn't defined, instead of a simple 404. CROW_CATCHALL_ROUTE(app) - ([](crow::response& res) { - res.body = "The URL does not seem to be correct."; - res.end(); - }); + ([](crow::response& res) { + if (res.code == 404) + { + res.body = "The URL does not seem to be correct."; + } + else if (res.code == 405) + { + res.body = "The HTTP method does not seem to be correct."; + } + res.end(); + }); app.port(18080).run(); } diff --git a/include/crow/routing.h b/include/crow/routing.h index 65746c6e5..35f799f77 100644 --- a/include/crow/routing.h +++ b/include/crow/routing.h @@ -1496,16 +1496,15 @@ namespace crow } else { - if (!found_bps.empty()) - found_bps.pop_back(); - - if (found_bps.empty()) + if (found_bps.size() < 2) { + found_bps.clear(); found_bps.push_back(blueprints_[bp_i[index]]); get_found_bp(bp_i, found_bps.back()->blueprints_, found_bps, ++index); } else { + found_bps.pop_back(); Blueprint* last_element = found_bps.back(); found_bps.push_back(last_element->blueprints_[bp_i[index]]); get_found_bp(bp_i, found_bps.back()->blueprints_, found_bps, ++index); @@ -1514,6 +1513,37 @@ namespace crow } } + /// Is used to handle errors, you insert the error code, found route, request, and response. and it'll either call the appropriate catchall route (considering the blueprint system) and send you a status string (which is mainly used for debug messages), or just set the response code to the proper error code. + std::string get_error(unsigned short code, std::tuple, routing_params>& found, const request& req, response& res) + { + res.code = code; + std::vector bps_found; + get_found_bp(std::get<1>(found), blueprints_, bps_found); + for (int i = bps_found.size()-1; i > 0; i--) + { + std::vector bpi = std::get<1>(found); + if (bps_found[i]->catchall_rule().has_handler()) + { + bps_found[i]->catchall_rule().handler_(req, res); +#ifdef CROW_ENABLE_DEBUG + return std::string("Redirected to Blueprint \"" + bps_found[i]->prefix() + "\" Catchall rule"); +#else + return std::string(); +#endif + } + } + if (catchall_rule_.has_handler()) + { + catchall_rule_.handler_(req, res); +#ifdef CROW_ENABLE_DEBUG + return std::string("Redirected to global Catchall rule"); +#else + return std::string(); +#endif + } + return std::string(); + } + void handle(const request& req, response& res) { HTTPMethod method_actual = req.method; @@ -1584,42 +1614,18 @@ namespace crow { for (auto& per_method: per_methods_) { - if (std::get<0>(per_method.trie.find(req.url))) + if (std::get<0>(per_method.trie.find(req.url))) //Route found, but in another method { - CROW_LOG_DEBUG << "Cannot match method " << req.url << " " << method_name(method_actual); - res = response(405); + std::string error_message(get_error(405, found, req, res)); + CROW_LOG_DEBUG << "Cannot match method " << req.url << " " << method_name(method_actual) << ". " << error_message; res.end(); return; } } + //Route does not exist anywhere - std::vector bps_found; - get_found_bp(std::get<1>(found), blueprints_, bps_found); - bool no_bp_catchall = true; - for (int i = bps_found.size()-1; i > 0; i--) - { - std::vector bpi = std::get<1>(found); - if (bps_found[i]->catchall_rule().has_handler()) - { - no_bp_catchall = false; - CROW_LOG_DEBUG << "Cannot match rules " << req.url << ". Redirecting to Blueprint \"" << bps_found[i]->prefix() << "\" Catchall rule"; - bps_found[i]->catchall_rule().handler_(req, res); - break; - } - } - if (no_bp_catchall) - { - if (catchall_rule_.has_handler()) - { - CROW_LOG_DEBUG << "Cannot match rules " << req.url << ". Redirecting to global Catchall rule"; - catchall_rule_.handler_(req, res); - } - else - { - CROW_LOG_DEBUG << "Cannot match rules " << req.url; - res = response(404); - } - } + std::string error_message(get_error(404, found, req, res)); + CROW_LOG_DEBUG << "Cannot match rules " << req.url << ". " << error_message; res.end(); return; } diff --git a/scripts/release.py b/scripts/release.py index 3072dd195..17965a499 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -17,5 +17,5 @@ os.mkdir(releasePath) os.chdir(releasePath) os.system("cmake -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DCPACK_PACKAGE_FILE_NAME=\"crow-{}\" .. && make -j5".format(version)) -os.system("sed -i 's/constexpr char VERSION\\[\\] = \"master\";/constexpr char VERSION\\[\\] = \"{}\";/g' crow_all.h".format(version)) -os.system("cpack") +os.system("sed -i 's/char VERSION\\[\\] = \"master\";/char VERSION\\[\\] = \"{}\";/g' crow_all.h".format(version)) +os.system("cpack -R {}".format(version)) diff --git a/tests/unittest.cpp b/tests/unittest.cpp index 8bc39ae1e..544b75db8 100644 --- a/tests/unittest.cpp +++ b/tests/unittest.cpp @@ -1,5 +1,6 @@ #define CATCH_CONFIG_MAIN #define CROW_ENABLE_COMPRESSION +#define CROW_ENABLE_DEBUG #define CROW_LOG_LEVEL 0 #define CROW_MAIN #include @@ -2094,7 +2095,7 @@ TEST_CASE("catchall") CROW_ROUTE(app, "/place")([](){return "place";}); - CROW_CATCHALL_ROUTE(app)([](){return "!place";}); + CROW_CATCHALL_ROUTE(app)([](response& res){res.body = "!place";}); CROW_ROUTE(app2, "/place")([](){return "place";}); @@ -2120,7 +2121,7 @@ TEST_CASE("catchall") app.handle(req, res); - CHECK(200 == res.code); + CHECK(404 == res.code); CHECK("!place" == res.body); }