From d1798b06d9490ae375e46ac9b19f8df11ce5e49c Mon Sep 17 00:00:00 2001 From: qicosmos Date: Thu, 18 Apr 2024 14:35:02 +0800 Subject: [PATCH] set default http handler (#557) --- include/cinatra/coro_http_connection.hpp | 123 +++++++++++++---------- include/cinatra/coro_http_server.hpp | 10 ++ tests/test_cinatra.cpp | 20 ++++ 3 files changed, 98 insertions(+), 55 deletions(-) diff --git a/include/cinatra/coro_http_connection.hpp b/include/cinatra/coro_http_connection.hpp index 6f25a9f1..f70550c3 100644 --- a/include/cinatra/coro_http_connection.hpp +++ b/include/cinatra/coro_http_connection.hpp @@ -192,78 +192,84 @@ class coro_http_connection co_await router_.route_coro(coro_handler, request_, response_, key); } else { - bool is_exist = false; - std::function - handler; - std::string method_str{parser_.method()}; - std::string url_path = method_str; - url_path.append(" ").append(parser_.url()); - std::tie(is_exist, handler, request_.params_) = - router_.get_router_tree()->get(url_path, method_str); - if (is_exist) { - if (handler) { - (handler)(request_, response_); - } - else { - response_.set_status(status_type::not_found); - } + if (default_handler_) { + default_handler_(request_, response_); } else { - bool is_coro_exist = false; - std::function( - coro_http_request & req, coro_http_response & resp)> - coro_handler; - - std::tie(is_coro_exist, coro_handler, request_.params_) = - router_.get_coro_router_tree()->get_coro(url_path, method_str); - - if (is_coro_exist) { - if (coro_handler) { - co_await coro_handler(request_, response_); + bool is_exist = false; + std::function + handler; + std::string method_str{parser_.method()}; + std::string url_path = method_str; + url_path.append(" ").append(parser_.url()); + std::tie(is_exist, handler, request_.params_) = + router_.get_router_tree()->get(url_path, method_str); + if (is_exist) { + if (handler) { + (handler)(request_, response_); } else { response_.set_status(status_type::not_found); } } else { - bool is_matched_regex_router = false; - // coro regex router - auto coro_regex_handlers = router_.get_coro_regex_handlers(); - if (coro_regex_handlers.size() != 0) { - for (auto &pair : coro_regex_handlers) { - std::string coro_regex_key{key}; - - if (std::regex_match(coro_regex_key, request_.matches_, - std::get<0>(pair))) { - auto coro_handler = std::get<1>(pair); - if (coro_handler) { - co_await coro_handler(request_, response_); - is_matched_regex_router = true; - } - } + bool is_coro_exist = false; + std::function( + coro_http_request & req, coro_http_response & resp)> + coro_handler; + + std::tie(is_coro_exist, coro_handler, request_.params_) = + router_.get_coro_router_tree()->get_coro(url_path, + method_str); + + if (is_coro_exist) { + if (coro_handler) { + co_await coro_handler(request_, response_); + } + else { + response_.set_status(status_type::not_found); } } - // regex router - if (!is_matched_regex_router) { - auto regex_handlers = router_.get_regex_handlers(); - if (regex_handlers.size() != 0) { - for (auto &pair : regex_handlers) { - std::string regex_key{key}; - if (std::regex_match(regex_key, request_.matches_, + else { + bool is_matched_regex_router = false; + // coro regex router + auto coro_regex_handlers = router_.get_coro_regex_handlers(); + if (coro_regex_handlers.size() != 0) { + for (auto &pair : coro_regex_handlers) { + std::string coro_regex_key{key}; + + if (std::regex_match(coro_regex_key, request_.matches_, std::get<0>(pair))) { - auto handler = std::get<1>(pair); - if (handler) { - (handler)(request_, response_); + auto coro_handler = std::get<1>(pair); + if (coro_handler) { + co_await coro_handler(request_, response_); is_matched_regex_router = true; } } } } + // regex router + if (!is_matched_regex_router) { + auto regex_handlers = router_.get_regex_handlers(); + if (regex_handlers.size() != 0) { + for (auto &pair : regex_handlers) { + std::string regex_key{key}; + if (std::regex_match(regex_key, request_.matches_, + std::get<0>(pair))) { + auto handler = std::get<1>(pair); + if (handler) { + (handler)(request_, response_); + is_matched_regex_router = true; + } + } + } + } + } + // not found + if (!is_matched_regex_router) + response_.set_status(status_type::not_found); } - // not found - if (!is_matched_regex_router) - response_.set_status(status_type::not_found); } } } @@ -407,6 +413,11 @@ class coro_http_connection void set_multi_buf(bool r) { multi_buf_ = r; } + void set_default_handler( + std::function &handler) { + default_handler_ = handler; + } + async_simple::coro::Lazy write_data(std::string_view message) { std::vector buffers; buffers.push_back(asio::buffer(message)); @@ -834,5 +845,7 @@ class coro_http_connection #endif bool need_shrink_every_time_ = false; bool multi_buf_ = true; + std::function + default_handler_ = nullptr; }; } // namespace cinatra diff --git a/include/cinatra/coro_http_server.hpp b/include/cinatra/coro_http_server.hpp index c0ab57f9..843ea3c4 100644 --- a/include/cinatra/coro_http_server.hpp +++ b/include/cinatra/coro_http_server.hpp @@ -550,6 +550,11 @@ class coro_http_server { void set_shrink_to_fit(bool r) { need_shrink_every_time_ = r; } + void set_default_handler( + std::function handler) { + default_handler_ = std::move(handler); + } + size_t connection_count() { std::scoped_lock lock(conn_mtx_); return connections_.size(); @@ -655,6 +660,9 @@ class coro_http_server { if (need_check_) { conn->set_check_timeout(true); } + if (default_handler_) { + conn->set_default_handler(default_handler_); + } #ifdef CINATRA_ENABLE_SSL if (use_ssl_) { @@ -915,6 +923,8 @@ class coro_http_server { #endif coro_http_router router_; bool need_shrink_every_time_ = false; + std::function + default_handler_ = nullptr; }; using http_server = coro_http_server; diff --git a/tests/test_cinatra.cpp b/tests/test_cinatra.cpp index d19057c0..a17ff3f9 100644 --- a/tests/test_cinatra.cpp +++ b/tests/test_cinatra.cpp @@ -397,6 +397,26 @@ async_simple::coro::Lazy test_collect_all() { thd.join(); } +TEST_CASE("test default http handler") { + coro_http_server server(1, 9001); + server.set_default_handler([](coro_http_request &req, + coro_http_response &resp) { + resp.set_status_and_content(status_type::ok, "It is from default handler"); + }); + server.async_start(); + + for (int i = 0; i < 5; i++) { + coro_http_client client{}; + async_simple::coro::syncAwait(client.connect("http://127.0.0.1:9001")); + auto data = client.get("/test"); + CHECK(data.resp_body == "It is from default handler"); + data = client.get("/test_again"); + CHECK(data.resp_body == "It is from default handler"); + data = client.get("/any"); + CHECK(data.resp_body == "It is from default handler"); + } +} + TEST_CASE("test request with out buffer") { std::string str; str.resize(10);