diff --git a/README.md b/README.md index 73b7ccb8..0acf467a 100644 --- a/README.md +++ b/README.md @@ -456,26 +456,15 @@ async_simple::coro::Lazy test_download() { ```c++ async_simple::coro::Lazy test_websocket() { coro_http_client client{}; - client.on_ws_close([](std::string_view reason) { - std::cout << "web socket close " << reason << std::endl; - }); - client.on_ws_msg([](resp_data data) { - if (data.net_err) { - std::cout << data.net_err.message() << "\n"; - return; - } - std::cout << data.resp_body << std::endl; - }); - auto r = co_await client.connect("ws://localhost:8090/ws"); if (r.net_err) { co_return; } - co_await client.write_websocket("hello websocket"); // mask as default. + co_await client.write_websocket("hello websocket"); auto data = co_await client.read_websocket(); CHECK(data.resp_body == "hello websocket"); - co_await client.write_websocket("test again", /*need_mask = */ false); + co_await client.write_websocket("test again"); data = co_await client.read_websocket(); CHECK(data.resp_body == "test again"); co_await client.write_websocket("ws close"); diff --git a/example/main.cpp b/example/main.cpp index ca13fc09..4727aadb 100644 --- a/example/main.cpp +++ b/example/main.cpp @@ -200,8 +200,7 @@ async_simple::coro::Lazy use_websocket() { co_return; } - auto result = - co_await client.write_websocket("hello websocket"); // mask as default. + auto result = co_await client.write_websocket("hello websocket"); assert(!result.net_err); auto data = co_await client.read_websocket(); assert(data.resp_body == "hello websocket"); 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/include/cinatra/ylt/coro_io/coro_io.hpp b/include/cinatra/ylt/coro_io/coro_io.hpp index ce6a1d0c..dbc22f04 100644 --- a/include/cinatra/ylt/coro_io/coro_io.hpp +++ b/include/cinatra/ylt/coro_io/coro_io.hpp @@ -38,7 +38,7 @@ class callback_awaitor_base { template class callback_awaitor_impl { public: - callback_awaitor_impl(Derived &awaitor, const Op &op) noexcept + callback_awaitor_impl(Derived &awaitor, Op &op) noexcept : awaitor(awaitor), op(op) {} constexpr bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle<> handle) noexcept { @@ -59,7 +59,7 @@ class callback_awaitor_base { private: Derived &awaitor; - const Op &op; + Op &op; }; public: @@ -87,7 +87,7 @@ class callback_awaitor_base { Derived *obj; }; template - callback_awaitor_impl await_resume(const Op &op) noexcept { + callback_awaitor_impl await_resume(Op &&op) noexcept { return callback_awaitor_impl{static_cast(*this), op}; } @@ -289,7 +289,7 @@ inline async_simple::coro::Lazy sleep_for(const Duration &d, co_await timer.async_await(); } template -inline async_simple::coro::Lazy sleep_for(const Duration &d) { +inline async_simple::coro::Lazy sleep_for(Duration d) { if (auto executor = co_await async_simple::CurrentExecutor(); executor != nullptr) { co_await async_simple::coro::sleep(d); @@ -302,7 +302,7 @@ inline async_simple::coro::Lazy sleep_for(const Duration &d) { template struct post_helper { - void operator()(auto handler) const { + void operator()(auto handler) { asio::dispatch(e, [this, handler]() { try { if constexpr (std::is_same_v>) { diff --git a/lang/coro_http_client_introduction.md b/lang/coro_http_client_introduction.md index 65c7091e..6123b160 100644 --- a/lang/coro_http_client_introduction.md +++ b/lang/coro_http_client_introduction.md @@ -423,13 +423,13 @@ auto r = async_simple::coro::syncAwait( ``` # websocket websocket 的支持需要3步: -- 设置读websocket 数据的回调函数; - 连接服务器; - 发送websocket 数据; +- 读websocket 数据; -设置websocket 读数据接口: +websocket 读数据接口: ```c++ -void on_ws_msg(std::function on_ws_msg); +async_simple::coro::Lazy read_websocket(); ``` websocket 连接服务器接口: ```c++ @@ -458,10 +458,8 @@ enum opcode : std::uint8_t { /// 发送websocket 数据 /// \param msg 要发送的websocket 数据 -/// \param need_mask 是否需要对数据进行mask,默认会mask /// \param op opcode 一般为text、binary或 close 等类型 async_simple::coro::Lazy write_websocket(std::string msg, - bool need_mask = true, opcode op = opcode::text); ``` diff --git a/lang/english/README.md b/lang/english/README.md index f9d1d971..983becb7 100644 --- a/lang/english/README.md +++ b/lang/english/README.md @@ -414,26 +414,15 @@ async_simple::coro::Lazy test_download() { ```c++ async_simple::coro::Lazy test_websocket() { coro_http_client client{}; - client.on_ws_close([](std::string_view reason) { - std::cout << "web socket close " << reason << std::endl; - }); - client.on_ws_msg([](resp_data data) { - if (data.net_err) { - std::cout << data.net_err.message() << "\n"; - return; - } - std::cout << data.resp_body << std::endl; - }); - auto r = co_await client.connect("ws://localhost:8090/ws"); if (r.net_err) { co_return; } - co_await client.write_websocket("hello websocket"); // mask as default. + co_await client.write_websocket("hello websocket"); auto data = co_await client.read_websocket(); CHECK(data.resp_body == "hello websocket"); - co_await client.write_websocket("test again", /*need_mask = */ false); + co_await client.write_websocket("test again"); data = co_await client.read_websocket(); CHECK(data.resp_body == "test again"); co_await client.write_websocket("ws close"); 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);