Skip to content

Commit

Permalink
set default http handler (qicosmos#557)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Apr 18, 2024
1 parent 4c4d2af commit d1798b0
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 55 deletions.
123 changes: 68 additions & 55 deletions include/cinatra/coro_http_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(coro_http_request & req,
coro_http_response & resp)>
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<async_simple::coro::Lazy<void>(
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<void(coro_http_request & req,
coro_http_response & resp)>
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<async_simple::coro::Lazy<void>(
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);
}
}
}
Expand Down Expand Up @@ -407,6 +413,11 @@ class coro_http_connection

void set_multi_buf(bool r) { multi_buf_ = r; }

void set_default_handler(
std::function<void(coro_http_request &, coro_http_response &)> &handler) {
default_handler_ = handler;
}

async_simple::coro::Lazy<bool> write_data(std::string_view message) {
std::vector<asio::const_buffer> buffers;
buffers.push_back(asio::buffer(message));
Expand Down Expand Up @@ -834,5 +845,7 @@ class coro_http_connection
#endif
bool need_shrink_every_time_ = false;
bool multi_buf_ = true;
std::function<void(coro_http_request &, coro_http_response &)>
default_handler_ = nullptr;
};
} // namespace cinatra
10 changes: 10 additions & 0 deletions include/cinatra/coro_http_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(coro_http_request &, coro_http_response &)> handler) {
default_handler_ = std::move(handler);
}

size_t connection_count() {
std::scoped_lock lock(conn_mtx_);
return connections_.size();
Expand Down Expand Up @@ -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_) {
Expand Down Expand Up @@ -915,6 +923,8 @@ class coro_http_server {
#endif
coro_http_router router_;
bool need_shrink_every_time_ = false;
std::function<void(coro_http_request &, coro_http_response &)>
default_handler_ = nullptr;
};

using http_server = coro_http_server;
Expand Down
20 changes: 20 additions & 0 deletions tests/test_cinatra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,26 @@ async_simple::coro::Lazy<void> 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);
Expand Down

0 comments on commit d1798b0

Please sign in to comment.