diff --git a/headers/enduro2d/core/network.hpp b/headers/enduro2d/core/network.hpp index f83c28f0..e69518d3 100644 --- a/headers/enduro2d/core/network.hpp +++ b/headers/enduro2d/core/network.hpp @@ -21,6 +21,46 @@ namespace e2d } }; + // + // request_network_error + // + + class request_network_error final : public exception { + public: + request_network_error() = default; + + request_network_error(str error) + : error_(std::move(error)) {} + + const char* what() const noexcept final { + return error_.empty() + ? "request network error" + : error_.c_str(); + } + private: + str error_; + }; + + // + // request_cancelled_exception + // + + class request_cancelled_exception : public exception { + public: + const char* what() const noexcept override { + return "request cancelled exception"; + } + }; + + // + // network_request + // + + struct network_request final { + net::request request; + stdex::promise promise; + }; + // // network // @@ -29,6 +69,9 @@ namespace e2d public: network(); ~network() noexcept; + + network_request request(net::request_builder& rb); + network_request request(net::request_builder&& rb); private: class internal_state; std::unique_ptr state_; diff --git a/sources/enduro2d/core/network.cpp b/sources/enduro2d/core/network.cpp index de184261..6a6f234d 100644 --- a/sources/enduro2d/core/network.cpp +++ b/sources/enduro2d/core/network.cpp @@ -22,4 +22,27 @@ namespace e2d network::network() : state_(new internal_state()) {} network::~network() noexcept = default; + + network_request network::request(net::request_builder& rb) { + return request(std::move(rb)); + } + + network_request network::request(net::request_builder&& rb) { + if ( rb.callback() ) { + throw bad_network_operation(); + } + stdex::promise promise; + rb.callback([promise](net::request request) mutable { + if ( request.is_done() ) { + promise.resolve(request.take()); + return; + } + if ( request.status() == net::req_status::cancelled ) { + promise.reject(request_cancelled_exception()); + } else { + promise.reject(request_network_error(request.get_error())); + } + }); + return {rb.send(), std::move(promise)}; + } } diff --git a/untests/sources/untests_core/network.cpp b/untests/sources/untests_core/network.cpp index efe60fe3..7cef69c8 100644 --- a/untests/sources/untests_core/network.cpp +++ b/untests/sources/untests_core/network.cpp @@ -11,9 +11,33 @@ TEST_CASE("network"){ network n; SECTION("request"){ - auto request = net::request_builder() - .url("http://httpbin.org/status/201") - .send(); - REQUIRE(request.take().http_code() == 201u); + { + auto nreq = n.request(net::request_builder() + .url("http://httpbin.org/status/201")); + + nreq.promise.then([](const net::response& response){ + REQUIRE(response.http_code() == 201u); + }).except([](std::exception_ptr){ + REQUIRE(false); + }).wait(); + } + { + auto nreq = n.request(net::request_builder() + .url("http://httpbin.org/delay/2")); + + REQUIRE(nreq.request.cancel()); + + nreq.promise.then([](const net::response&){ + REQUIRE(false); + }).except([](std::exception_ptr e){ + try { + std::rethrow_exception(e); + } catch (const request_cancelled_exception&) { + REQUIRE(true); + } catch (...) { + REQUIRE(false); + } + }).wait(); + } } }