rename perfrom to send and update to perform

This commit is contained in:
2019-06-26 06:54:52 +07:00
parent 5bf2d47e64
commit 23c344c8a9
3 changed files with 97 additions and 102 deletions

View File

@@ -104,10 +104,6 @@ namespace curly_hpp
response& operator=(const response&) = delete; response& operator=(const response&) = delete;
explicit response(response_code_t rc) noexcept; explicit response(response_code_t rc) noexcept;
response(response_code_t rc, headers_t h) noexcept;
response(response_code_t rc, content_t c) noexcept;
response(response_code_t rc, headers_t h, content_t c) noexcept;
response_code_t code() const noexcept; response_code_t code() const noexcept;
content_t& content() noexcept; content_t& content() noexcept;
@@ -209,7 +205,7 @@ namespace curly_hpp
downloader_uptr& downloader() noexcept; downloader_uptr& downloader() noexcept;
const downloader_uptr& downloader() const noexcept; const downloader_uptr& downloader() const noexcept;
request perform(); request send();
template < typename Uploader, typename... Args > template < typename Uploader, typename... Args >
request_builder& uploader(Args&&... args) { request_builder& uploader(Args&&... args) {
@@ -238,10 +234,10 @@ namespace curly_hpp
namespace curly_hpp namespace curly_hpp
{ {
class auto_updater { class auto_performer {
public: public:
auto_updater(); auto_performer();
~auto_updater() noexcept; ~auto_performer() noexcept;
time_ms_t wait_activity() const noexcept; time_ms_t wait_activity() const noexcept;
void wait_activity(time_ms_t ms) noexcept; void wait_activity(time_ms_t ms) noexcept;
@@ -254,9 +250,6 @@ namespace curly_hpp
namespace curly_hpp namespace curly_hpp
{ {
void update(); void perform();
void wait_activity(time_ms_t ms); void wait_activity(time_ms_t ms);
request perform(request_builder& rb);
request perform(request_builder&& rb);
} }

View File

@@ -230,19 +230,6 @@ namespace curly_hpp
response::response(response_code_t rc) noexcept response::response(response_code_t rc) noexcept
: code_(rc) {} : code_(rc) {}
response::response(response_code_t rc, headers_t h) noexcept
: code_(rc)
, headers_(std::move(h)) {}
response::response(response_code_t rc, content_t c) noexcept
: code_(rc)
, content_(std::move(c)) {}
response::response(response_code_t rc, headers_t h, content_t c) noexcept
: code_(rc)
, headers_(std::move(h))
, content_(std::move(c)) {}
response_code_t response::code() const noexcept { response_code_t response::code() const noexcept {
return code_; return code_;
} }
@@ -376,16 +363,28 @@ namespace curly_hpp
return false; return false;
} }
long response_code = 0; long code = 0;
curl_easy_getinfo( if ( CURLE_OK != curl_easy_getinfo(
handle_.get(), handle_.get(),
CURLINFO_RESPONSE_CODE, CURLINFO_RESPONSE_CODE,
&response_code); &code) || !code )
{
status_ = statuses::failed;
cond_var_.notify_all();
return false;
}
response_ = response( try {
static_cast<response_code_t>(response_code), response_ = response(static_cast<response_code_t>(code));
std::move(response_headers_), response_.content() = std::move(response_content_);
std::move(response_content_)); response_.headers() = std::move(response_headers_);
response_.uploader() = std::move(uploader_);
response_.downloader() = std::move(downloader_);
} catch (...) {
status_ = statuses::failed;
cond_var_.notify_all();
return false;
}
status_ = statuses::done; status_ = statuses::done;
error_.clear(); error_.clear();
@@ -716,40 +715,65 @@ namespace curly_hpp
return downloader_; return downloader_;
} }
request request_builder::perform() { request request_builder::send() {
return ::perform(*this); return curl_state::with([this](CURLM* curlm){
handle_t handle{
curl_easy_init(),
&curl_easy_cleanup};
if ( !handle ) {
throw exception("curly_hpp: failed to curl_easy_init");
}
auto sreq = std::make_shared<request::internal_state>(
std::move(handle),
std::move(*this));
if ( CURLM_OK != curl_multi_add_handle(curlm, sreq->handle().get()) ) {
throw exception("curly_hpp: failed to curl_multi_add_handle");
}
try {
handles.emplace(sreq->handle().get(), sreq);
} catch (...) {
curl_multi_remove_handle(curlm, sreq->handle().get());
throw;
}
return request(sreq);
});
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// //
// auto_updater // auto_performer
// //
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
namespace curly_hpp namespace curly_hpp
{ {
auto_updater::auto_updater() { auto_performer::auto_performer() {
thread_ = std::thread([this](){ thread_ = std::thread([this](){
while ( !done_ ) { while ( !done_ ) {
::update(); curly_hpp::perform();
::wait_activity(wait_activity()); curly_hpp::wait_activity(wait_activity());
} }
}); });
} }
auto_updater::~auto_updater() noexcept { auto_performer::~auto_performer() noexcept {
done_.store(true); done_.store(true);
if ( thread_.joinable() ) { if ( thread_.joinable() ) {
thread_.join(); thread_.join();
} }
} }
time_ms_t auto_updater::wait_activity() const noexcept { time_ms_t auto_performer::wait_activity() const noexcept {
return wait_activity_; return wait_activity_;
} }
void auto_updater::wait_activity(time_ms_t ms) noexcept { void auto_performer::wait_activity(time_ms_t ms) noexcept {
wait_activity_ = ms; wait_activity_ = ms;
} }
} }
@@ -762,7 +786,7 @@ namespace curly_hpp
namespace curly_hpp namespace curly_hpp
{ {
void update() { void perform() {
curl_state::with([](CURLM* curlm){ curl_state::with([](CURLM* curlm){
int running_handles = 0; int running_handles = 0;
curl_multi_perform(curlm, &running_handles); curl_multi_perform(curlm, &running_handles);
@@ -809,26 +833,4 @@ namespace curly_hpp
curl_multi_wait(curlm, nullptr, 0, static_cast<int>(ms.count()), nullptr); curl_multi_wait(curlm, nullptr, 0, static_cast<int>(ms.count()), nullptr);
}); });
} }
request perform(request_builder& rb) {
return perform(std::move(rb));
}
request perform(request_builder&& rb) {
return curl_state::with([&rb](CURLM* curlm){
handle_t handle{curl_easy_init(), &curl_easy_cleanup};
if ( !handle ) {
throw exception("curly_hpp: failed to curl_easy_init");
}
auto sreq = std::make_shared<request::internal_state>(std::move(handle), std::move(rb));
curl_multi_add_handle(curlm, sreq->handle().get());
try {
handles.emplace(sreq->handle().get(), sreq);
} catch (...) {
curl_multi_remove_handle(curlm, sreq->handle().get());
throw;
}
return request(sreq);
});
}
} }

View File

@@ -48,10 +48,10 @@ namespace
} }
TEST_CASE("curly"){ TEST_CASE("curly"){
net::auto_updater updater; net::auto_performer performer;
SECTION("wait") { SECTION("wait") {
auto req = net::request_builder("https://httpbin.org/delay/1").perform(); auto req = net::request_builder("https://httpbin.org/delay/1").send();
REQUIRE(req.status() == net::request::statuses::pending); REQUIRE(req.status() == net::request::statuses::pending);
REQUIRE(req.wait() == net::request::statuses::done); REQUIRE(req.wait() == net::request::statuses::done);
REQUIRE(req.status() == net::request::statuses::done); REQUIRE(req.status() == net::request::statuses::done);
@@ -61,7 +61,7 @@ TEST_CASE("curly"){
} }
SECTION("error") { SECTION("error") {
auto req = net::request_builder("|||").perform(); auto req = net::request_builder("|||").send();
REQUIRE(req.wait() == net::request::statuses::failed); REQUIRE(req.wait() == net::request::statuses::failed);
REQUIRE(req.status() == net::request::statuses::failed); REQUIRE(req.status() == net::request::statuses::failed);
REQUIRE_FALSE(req.error().empty()); REQUIRE_FALSE(req.error().empty());
@@ -69,13 +69,13 @@ TEST_CASE("curly"){
SECTION("cancel") { SECTION("cancel") {
{ {
auto req = net::request_builder("https://httpbin.org/delay/1").perform(); auto req = net::request_builder("https://httpbin.org/delay/1").send();
REQUIRE(req.cancel()); REQUIRE(req.cancel());
REQUIRE(req.status() == net::request::statuses::canceled); REQUIRE(req.status() == net::request::statuses::canceled);
REQUIRE(req.error().empty()); REQUIRE(req.error().empty());
} }
{ {
auto req = net::request_builder("https://httpbin.org/status/200").perform(); auto req = net::request_builder("https://httpbin.org/status/200").send();
REQUIRE(req.wait() == net::request::statuses::done); REQUIRE(req.wait() == net::request::statuses::done);
REQUIRE_FALSE(req.cancel()); REQUIRE_FALSE(req.cancel());
REQUIRE(req.status() == net::request::statuses::done); REQUIRE(req.status() == net::request::statuses::done);
@@ -85,13 +85,13 @@ TEST_CASE("curly"){
SECTION("get") { SECTION("get") {
{ {
auto req = net::request_builder("https://httpbin.org/status/204").perform(); auto req = net::request_builder("https://httpbin.org/status/204").send();
auto resp = req.get(); auto resp = req.get();
REQUIRE(req.status() == net::request::statuses::empty); REQUIRE(req.status() == net::request::statuses::empty);
REQUIRE(resp.code() == 204u); REQUIRE(resp.code() == 204u);
} }
{ {
auto req = net::request_builder("https://httpbin.org/delay/2").perform(); auto req = net::request_builder("https://httpbin.org/delay/2").send();
REQUIRE(req.cancel()); REQUIRE(req.cancel());
REQUIRE_THROWS_AS(req.get(), net::exception); REQUIRE_THROWS_AS(req.get(), net::exception);
REQUIRE(req.status() == net::request::statuses::canceled); REQUIRE(req.status() == net::request::statuses::canceled);
@@ -99,7 +99,7 @@ TEST_CASE("curly"){
{ {
auto req = net::request_builder("https://httpbin.org/delay/2") auto req = net::request_builder("https://httpbin.org/delay/2")
.response_timeout(net::time_sec_t(0)) .response_timeout(net::time_sec_t(0))
.perform(); .send();
REQUIRE(req.wait() == net::request::statuses::timeout); REQUIRE(req.wait() == net::request::statuses::timeout);
REQUIRE_THROWS_AS(req.get(), net::exception); REQUIRE_THROWS_AS(req.get(), net::exception);
REQUIRE(req.status() == net::request::statuses::timeout); REQUIRE(req.status() == net::request::statuses::timeout);
@@ -111,75 +111,75 @@ TEST_CASE("curly"){
auto req0 = net::request_builder() auto req0 = net::request_builder()
.url("https://httpbin.org/put") .url("https://httpbin.org/put")
.method(net::methods::put) .method(net::methods::put)
.perform(); .send();
REQUIRE(req0.get().code() == 200u); REQUIRE(req0.get().code() == 200u);
auto req1 = net::request_builder() auto req1 = net::request_builder()
.url("https://httpbin.org/put") .url("https://httpbin.org/put")
.method(net::methods::get) .method(net::methods::get)
.perform(); .send();
REQUIRE(req1.get().code() == 405u); REQUIRE(req1.get().code() == 405u);
auto req2 = net::request_builder() auto req2 = net::request_builder()
.url("https://httpbin.org/put") .url("https://httpbin.org/put")
.method(net::methods::head) .method(net::methods::head)
.perform(); .send();
REQUIRE(req2.get().code() == 405u); REQUIRE(req2.get().code() == 405u);
auto req3 = net::request_builder() auto req3 = net::request_builder()
.url("https://httpbin.org/put") .url("https://httpbin.org/put")
.method(net::methods::post) .method(net::methods::post)
.perform(); .send();
REQUIRE(req3.get().code() == 405u); REQUIRE(req3.get().code() == 405u);
} }
{ {
auto req0 = net::request_builder() auto req0 = net::request_builder()
.url("https://httpbin.org/get") .url("https://httpbin.org/get")
.method(net::methods::put) .method(net::methods::put)
.perform(); .send();
REQUIRE(req0.get().code() == 405u); REQUIRE(req0.get().code() == 405u);
auto req1 = net::request_builder() auto req1 = net::request_builder()
.url("https://httpbin.org/get") .url("https://httpbin.org/get")
.method(net::methods::get) .method(net::methods::get)
.perform(); .send();
REQUIRE(req1.get().code() == 200u); REQUIRE(req1.get().code() == 200u);
auto req2 = net::request_builder() auto req2 = net::request_builder()
.url("https://httpbin.org/get") .url("https://httpbin.org/get")
.method(net::methods::head) .method(net::methods::head)
.perform(); .send();
REQUIRE(req2.get().code() == 200u); REQUIRE(req2.get().code() == 200u);
auto req3 = net::request_builder() auto req3 = net::request_builder()
.url("https://httpbin.org/get") .url("https://httpbin.org/get")
.method(net::methods::post) .method(net::methods::post)
.perform(); .send();
REQUIRE(req3.get().code() == 405u); REQUIRE(req3.get().code() == 405u);
} }
{ {
auto req0 = net::request_builder() auto req0 = net::request_builder()
.url("https://httpbin.org/post") .url("https://httpbin.org/post")
.method(net::methods::put) .method(net::methods::put)
.perform(); .send();
REQUIRE(req0.get().code() == 405u); REQUIRE(req0.get().code() == 405u);
auto req1 = net::request_builder() auto req1 = net::request_builder()
.url("https://httpbin.org/post") .url("https://httpbin.org/post")
.method(net::methods::get) .method(net::methods::get)
.perform(); .send();
REQUIRE(req1.get().code() == 405u); REQUIRE(req1.get().code() == 405u);
auto req2 = net::request_builder() auto req2 = net::request_builder()
.url("https://httpbin.org/post") .url("https://httpbin.org/post")
.method(net::methods::head) .method(net::methods::head)
.perform(); .send();
REQUIRE(req2.get().code() == 405u); REQUIRE(req2.get().code() == 405u);
auto req3 = net::request_builder() auto req3 = net::request_builder()
.url("https://httpbin.org/post") .url("https://httpbin.org/post")
.method(net::methods::post) .method(net::methods::post)
.perform(); .send();
REQUIRE(req3.get().code() == 200u); REQUIRE(req3.get().code() == 200u);
} }
} }
@@ -189,28 +189,28 @@ TEST_CASE("curly"){
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/status/200") .url("https://httpbin.org/status/200")
.method(net::methods::put) .method(net::methods::put)
.perform(); .send();
REQUIRE(req.get().code() == 200u); REQUIRE(req.get().code() == 200u);
} }
{ {
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/status/201") .url("https://httpbin.org/status/201")
.method(net::methods::get) .method(net::methods::get)
.perform(); .send();
REQUIRE(req.get().code() == 201u); REQUIRE(req.get().code() == 201u);
} }
{ {
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/status/202") .url("https://httpbin.org/status/202")
.method(net::methods::head) .method(net::methods::head)
.perform(); .send();
REQUIRE(req.get().code() == 202u); REQUIRE(req.get().code() == 202u);
} }
{ {
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/status/203") .url("https://httpbin.org/status/203")
.method(net::methods::post) .method(net::methods::post)
.perform(); .send();
REQUIRE(req.get().code() == 203u); REQUIRE(req.get().code() == 203u);
} }
} }
@@ -220,7 +220,7 @@ TEST_CASE("curly"){
.url("https://httpbin.org/headers") .url("https://httpbin.org/headers")
.header("Custom-Header-1", "custom_header_value_1") .header("Custom-Header-1", "custom_header_value_1")
.header("Custom-Header-2", "custom header value 2") .header("Custom-Header-2", "custom header value 2")
.perform(); .send();
const auto resp = req.get(); const auto resp = req.get();
const auto content_j = json::parse(resp.content().as_string_view()); const auto content_j = json::parse(resp.content().as_string_view());
REQUIRE(content_j["headers"]["Custom-Header-1"] == "custom_header_value_1"); REQUIRE(content_j["headers"]["Custom-Header-1"] == "custom_header_value_1");
@@ -232,7 +232,7 @@ TEST_CASE("curly"){
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/response-headers?hello=world&world=hello") .url("https://httpbin.org/response-headers?hello=world&world=hello")
.method(net::methods::get) .method(net::methods::get)
.perform(); .send();
const auto resp = req.get(); const auto resp = req.get();
const auto content_j = json::parse(resp.content().as_string_view()); const auto content_j = json::parse(resp.content().as_string_view());
REQUIRE(content_j["hello"] == "world"); REQUIRE(content_j["hello"] == "world");
@@ -242,7 +242,7 @@ TEST_CASE("curly"){
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/response-headers?hello=world&world=hello") .url("https://httpbin.org/response-headers?hello=world&world=hello")
.method(net::methods::post) .method(net::methods::post)
.perform(); .send();
const auto resp = req.get(); const auto resp = req.get();
const auto content_j = json::parse(resp.content().as_string_view()); const auto content_j = json::parse(resp.content().as_string_view());
REQUIRE(content_j["hello"] == "world"); REQUIRE(content_j["hello"] == "world");
@@ -254,7 +254,7 @@ TEST_CASE("curly"){
{ {
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/base64/SFRUUEJJTiBpcyBhd2Vzb21l") .url("https://httpbin.org/base64/SFRUUEJJTiBpcyBhd2Vzb21l")
.perform(); .send();
const auto resp = req.get(); const auto resp = req.get();
REQUIRE(resp.content().as_string_view() == "HTTPBIN is awesome"); REQUIRE(resp.content().as_string_view() == "HTTPBIN is awesome");
REQUIRE(req.error().empty()); REQUIRE(req.error().empty());
@@ -263,7 +263,7 @@ TEST_CASE("curly"){
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/delay/10") .url("https://httpbin.org/delay/10")
.response_timeout(net::time_sec_t(0)) .response_timeout(net::time_sec_t(0))
.perform(); .send();
REQUIRE(req.wait() == net::request::statuses::timeout); REQUIRE(req.wait() == net::request::statuses::timeout);
REQUIRE_FALSE(req.error().empty()); REQUIRE_FALSE(req.error().empty());
} }
@@ -271,7 +271,7 @@ TEST_CASE("curly"){
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/delay/10") .url("https://httpbin.org/delay/10")
.response_timeout(net::time_sec_t(1)) .response_timeout(net::time_sec_t(1))
.perform(); .send();
REQUIRE(req.wait() == net::request::statuses::timeout); REQUIRE(req.wait() == net::request::statuses::timeout);
REQUIRE_FALSE(req.error().empty()); REQUIRE_FALSE(req.error().empty());
} }
@@ -282,7 +282,7 @@ TEST_CASE("curly"){
auto resp = net::request_builder() auto resp = net::request_builder()
.url("https://httpbin.org/image/png") .url("https://httpbin.org/image/png")
.method(net::methods::get) .method(net::methods::get)
.perform().get(); .send().get();
REQUIRE(resp.code() == 200u); REQUIRE(resp.code() == 200u);
REQUIRE(resp.headers().count("Content-Type")); REQUIRE(resp.headers().count("Content-Type"));
REQUIRE(resp.headers().at("Content-Type") == "image/png"); REQUIRE(resp.headers().at("Content-Type") == "image/png");
@@ -293,7 +293,7 @@ TEST_CASE("curly"){
auto resp = net::request_builder() auto resp = net::request_builder()
.url("https://httpbin.org/image/jpeg") .url("https://httpbin.org/image/jpeg")
.method(net::methods::get) .method(net::methods::get)
.perform().get(); .send().get();
REQUIRE(resp.code() == 200u); REQUIRE(resp.code() == 200u);
REQUIRE(resp.headers().count("Content-Type")); REQUIRE(resp.headers().count("Content-Type"));
REQUIRE(resp.headers().at("Content-Type") == "image/jpeg"); REQUIRE(resp.headers().at("Content-Type") == "image/jpeg");
@@ -307,21 +307,21 @@ TEST_CASE("curly"){
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/redirect/2") .url("https://httpbin.org/redirect/2")
.method(net::methods::get) .method(net::methods::get)
.perform(); .send();
REQUIRE(req.get().code() == 200u); REQUIRE(req.get().code() == 200u);
} }
{ {
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/absolute-redirect/2") .url("https://httpbin.org/absolute-redirect/2")
.method(net::methods::get) .method(net::methods::get)
.perform(); .send();
REQUIRE(req.get().code() == 200u); REQUIRE(req.get().code() == 200u);
} }
{ {
auto req = net::request_builder() auto req = net::request_builder()
.url("https://httpbin.org/relative-redirect/2") .url("https://httpbin.org/relative-redirect/2")
.method(net::methods::get) .method(net::methods::get)
.perform(); .send();
REQUIRE(req.get().code() == 200u); REQUIRE(req.get().code() == 200u);
} }
} }
@@ -333,7 +333,7 @@ TEST_CASE("curly"){
.method(net::methods::put) .method(net::methods::put)
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.content(R"({"hello":"world"})") .content(R"({"hello":"world"})")
.perform().get(); .send().get();
const auto content_j = json::parse(resp.content().as_string_view()); const auto content_j = json::parse(resp.content().as_string_view());
REQUIRE(content_j["data"] == R"({"hello":"world"})"); REQUIRE(content_j["data"] == R"({"hello":"world"})");
} }
@@ -343,7 +343,7 @@ TEST_CASE("curly"){
.method(net::methods::post) .method(net::methods::post)
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.content(R"({"hello":"world"})") .content(R"({"hello":"world"})")
.perform().get(); .send().get();
const auto content_j = json::parse(resp.content().as_string_view()); const auto content_j = json::parse(resp.content().as_string_view());
REQUIRE(content_j["data"] == R"({"hello":"world"})"); REQUIRE(content_j["data"] == R"({"hello":"world"})");
} }
@@ -353,7 +353,7 @@ TEST_CASE("curly"){
.method(net::methods::post) .method(net::methods::post)
.header("Content-Type", "application/x-www-form-urlencoded") .header("Content-Type", "application/x-www-form-urlencoded")
.content("hello=world&world=hello") .content("hello=world&world=hello")
.perform().get(); .send().get();
const auto content_j = json::parse(resp.content().as_string_view()); const auto content_j = json::parse(resp.content().as_string_view());
REQUIRE(content_j["form"]["hello"] == "world"); REQUIRE(content_j["form"]["hello"] == "world");
REQUIRE(content_j["form"]["world"] == "hello"); REQUIRE(content_j["form"]["world"] == "hello");