diff --git a/README.md b/README.md index 0c69978..2ae7217 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ if ( request.is_done() ) { std::cout << "Error message: " << request.get_error() << std::endl; } -// Error message: Couldn't resolve host name +// Error message: Could not resolve host: unavailable.site.com ``` ### Request Callbacks diff --git a/sources/curly.hpp/curly.cpp b/sources/curly.hpp/curly.cpp index 8484ff8..5a73c01 100644 --- a/sources/curly.hpp/curly.cpp +++ b/sources/curly.hpp/curly.cpp @@ -325,6 +325,7 @@ namespace curly_hpp curl_easy_setopt(curlh_.get(), CURLOPT_TCP_KEEPALIVE, 1l); curl_easy_setopt(curlh_.get(), CURLOPT_BUFFERSIZE, 65536l); curl_easy_setopt(curlh_.get(), CURLOPT_USE_SSL, CURLUSESSL_ALL); + curl_easy_setopt(curlh_.get(), CURLOPT_ERRORBUFFER, error_buffer_); curl_easy_setopt(curlh_.get(), CURLOPT_READDATA, this); curl_easy_setopt(curlh_.get(), CURLOPT_READFUNCTION, &s_upload_callback_); @@ -488,24 +489,29 @@ namespace curly_hpp return false; } - switch ( err ) { - case CURLE_OPERATION_TIMEDOUT: - status_ = req_status::timeout; - break; - case CURLE_READ_ERROR: - case CURLE_WRITE_ERROR: - case CURLE_ABORTED_BY_CALLBACK: - status_ = req_status::cancelled; - break; - default: - status_ = req_status::failed; - break; - } - try { - error_ = curl_easy_strerror(err); + switch ( err ) { + case CURLE_OPERATION_TIMEDOUT: + status_ = req_status::timeout; + error_.assign("Operation timeout"); + break; + case CURLE_READ_ERROR: + case CURLE_WRITE_ERROR: + case CURLE_ABORTED_BY_CALLBACK: + status_ = req_status::cancelled; + error_.assign("Callback aborted"); + break; + default: + status_ = req_status::failed; + error_.assign(error_buffer_[0] + ? error_buffer_ + : "Unknown error"); + break; + } } catch (...) { - // nothing + status_ = req_status::failed; + cvar_.notify_all(); + return true; } cvar_.notify_all(); @@ -518,8 +524,14 @@ namespace curly_hpp return false; } - status_ = req_status::cancelled; - error_.clear(); + try { + status_ = req_status::cancelled; + error_.assign("Operation cancelled"); + } catch (...) { + status_ = req_status::failed; + cvar_.notify_all(); + return true; + } cvar_.notify_all(); return true; @@ -744,6 +756,7 @@ namespace curly_hpp float progress_{0.f}; req_status status_{req_status::pending}; std::string error_{"Unknown error"}; + char error_buffer_[CURL_ERROR_SIZE]{'\0'}; private: mutable std::mutex mutex_; mutable std::condition_variable cvar_; diff --git a/untests/curly_tests.cpp b/untests/curly_tests.cpp index e14c1b4..836d7d2 100644 --- a/untests/curly_tests.cpp +++ b/untests/curly_tests.cpp @@ -137,7 +137,7 @@ TEST_CASE("curly") { auto req = net::request_builder("https://httpbin.org/delay/1").send(); REQUIRE(req.cancel()); REQUIRE(req.status() == net::req_status::cancelled); - REQUIRE(req.get_error().empty()); + REQUIRE_FALSE(req.get_error().empty()); } { auto req = net::request_builder("https://httpbin.org/status/200").send(); @@ -881,7 +881,7 @@ TEST_CASE("curly") { ++call_once; REQUIRE_FALSE(request.is_done()); REQUIRE(request.status() == net::req_status::cancelled); - REQUIRE(request.get_error().empty()); + REQUIRE_FALSE(request.get_error().empty()); }).send(); REQUIRE(req.cancel()); REQUIRE(req.wait_callback() == net::req_status::cancelled); @@ -1002,7 +1002,7 @@ TEST_CASE("curly_examples") { std::cout << "Error message: " << request.get_error() << std::endl; } - // Error message: Couldn't resolve host name + // Error message: Could not resolve host: unavailable.site.com } SECTION("Request Callbacks") {