mirror of
https://github.com/BlackMATov/curly.hpp.git
synced 2026-01-04 15:16:51 +07:00
separated data structure of body
This commit is contained in:
@@ -27,8 +27,10 @@ namespace curly_hpp
|
|||||||
explicit exception(const std::string& what);
|
explicit exception(const std::string& what);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct case_insensitive_compare {
|
struct icase_compare {
|
||||||
bool operator()(const std::string& l, const std::string& r) const noexcept;
|
bool operator()(
|
||||||
|
const std::string& l,
|
||||||
|
const std::string& r) const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class methods {
|
enum class methods {
|
||||||
@@ -38,15 +40,12 @@ namespace curly_hpp
|
|||||||
post
|
post
|
||||||
};
|
};
|
||||||
|
|
||||||
using headers_t = std::map<
|
|
||||||
std::string, std::string,
|
|
||||||
case_insensitive_compare>;
|
|
||||||
|
|
||||||
using body_t = std::vector<char>;
|
|
||||||
using response_code_t = std::uint16_t;
|
using response_code_t = std::uint16_t;
|
||||||
|
using headers_t = std::map<std::string, std::string, icase_compare>;
|
||||||
|
|
||||||
using sec_t = std::chrono::seconds;
|
using time_sec_t = std::chrono::seconds;
|
||||||
using ms_t = std::chrono::milliseconds;
|
using time_ms_t = std::chrono::milliseconds;
|
||||||
|
using time_point_t = std::chrono::steady_clock::time_point;
|
||||||
|
|
||||||
class upload_handler {
|
class upload_handler {
|
||||||
public:
|
public:
|
||||||
@@ -63,84 +62,67 @@ namespace curly_hpp
|
|||||||
|
|
||||||
using uploader_uptr = std::unique_ptr<upload_handler>;
|
using uploader_uptr = std::unique_ptr<upload_handler>;
|
||||||
using downloader_uptr = std::unique_ptr<download_handler>;
|
using downloader_uptr = std::unique_ptr<download_handler>;
|
||||||
|
}
|
||||||
|
|
||||||
class request_builder {
|
namespace curly_hpp
|
||||||
|
{
|
||||||
|
class content_t {
|
||||||
public:
|
public:
|
||||||
request_builder() = default;
|
content_t() = default;
|
||||||
|
|
||||||
request_builder(request_builder&&) = default;
|
content_t(content_t&&) = default;
|
||||||
request_builder& operator=(request_builder&&) = default;
|
content_t& operator=(content_t&&) = default;
|
||||||
|
|
||||||
request_builder(const request_builder&) = delete;
|
content_t(const content_t&) = default;
|
||||||
request_builder& operator=(const request_builder&) = delete;
|
content_t& operator=(const content_t&) = default;
|
||||||
|
|
||||||
explicit request_builder(methods m) noexcept;
|
content_t(std::string_view data);
|
||||||
explicit request_builder(std::string u) noexcept;
|
content_t(std::vector<char> data) noexcept;
|
||||||
explicit request_builder(methods m, std::string u) noexcept;
|
|
||||||
|
|
||||||
request_builder& url(std::string u) noexcept;
|
std::size_t size() const noexcept;
|
||||||
request_builder& method(methods m) noexcept;
|
std::vector<char>& data() noexcept;
|
||||||
request_builder& header(std::string key, std::string value);
|
const std::vector<char>& data() const noexcept;
|
||||||
|
|
||||||
request_builder& verbose(bool v) noexcept;
|
std::string as_string_copy() const;
|
||||||
request_builder& verification(bool v) noexcept;
|
std::string_view as_string_view() const noexcept;
|
||||||
request_builder& response_timeout(sec_t t) noexcept;
|
|
||||||
request_builder& connection_timeout(sec_t t) noexcept;
|
|
||||||
request_builder& redirections(std::uint32_t r) noexcept;
|
|
||||||
|
|
||||||
request_builder& body(body_t b) noexcept;
|
|
||||||
request_builder& body(std::string_view b);
|
|
||||||
request_builder& uploader(uploader_uptr u) noexcept;
|
|
||||||
request_builder& downloader(downloader_uptr d) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] const std::string& url() const noexcept;
|
|
||||||
[[nodiscard]] methods method() const noexcept;
|
|
||||||
[[nodiscard]] const headers_t& headers() const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] bool verbose() const noexcept;
|
|
||||||
[[nodiscard]] bool verification() const noexcept;
|
|
||||||
[[nodiscard]] sec_t response_timeout() const noexcept;
|
|
||||||
[[nodiscard]] sec_t connection_timeout() const noexcept;
|
|
||||||
[[nodiscard]] std::uint32_t redirections() const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] body_t& body() noexcept;
|
|
||||||
[[nodiscard]] const body_t& body() const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] uploader_uptr& uploader() noexcept;
|
|
||||||
[[nodiscard]] const uploader_uptr& uploader() const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] downloader_uptr& downloader() noexcept;
|
|
||||||
[[nodiscard]] const downloader_uptr& downloader() const noexcept;
|
|
||||||
private:
|
private:
|
||||||
std::string url_;
|
std::vector<char> data_;
|
||||||
methods method_{methods::get};
|
|
||||||
headers_t headers_;
|
|
||||||
bool verbose_{false};
|
|
||||||
bool verification_{true};
|
|
||||||
sec_t response_timeout_{60u};
|
|
||||||
sec_t connection_timeout_{20u};
|
|
||||||
std::uint32_t redirections_{~0u};
|
|
||||||
private:
|
|
||||||
body_t body_;
|
|
||||||
uploader_uptr uploader_;
|
|
||||||
downloader_uptr downloader_;
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace curly_hpp
|
||||||
|
{
|
||||||
class response {
|
class response {
|
||||||
public:
|
public:
|
||||||
response() = default;
|
response() = default;
|
||||||
response(response_code_t c, body_t b, headers_t h);
|
|
||||||
|
response(response&&) = default;
|
||||||
|
response& operator=(response&&) = default;
|
||||||
|
|
||||||
|
response(const response&) = default;
|
||||||
|
response& operator=(const response&) = default;
|
||||||
|
|
||||||
|
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;
|
||||||
const body_t& body() const noexcept;
|
|
||||||
|
content_t& content() noexcept;
|
||||||
|
const content_t& content() const noexcept;
|
||||||
|
|
||||||
|
headers_t& headers() noexcept;
|
||||||
const headers_t& headers() const noexcept;
|
const headers_t& headers() const noexcept;
|
||||||
std::string_view body_as_string() const noexcept;
|
|
||||||
private:
|
private:
|
||||||
response_code_t code_{0u};
|
response_code_t code_{0u};
|
||||||
body_t body_;
|
content_t content_;
|
||||||
headers_t headers_;
|
headers_t headers_;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace curly_hpp
|
||||||
|
{
|
||||||
class request {
|
class request {
|
||||||
public:
|
public:
|
||||||
enum class statuses {
|
enum class statuses {
|
||||||
@@ -165,22 +147,93 @@ namespace curly_hpp
|
|||||||
private:
|
private:
|
||||||
internal_state_ptr state_;
|
internal_state_ptr state_;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace curly_hpp
|
||||||
|
{
|
||||||
|
class request_builder {
|
||||||
|
public:
|
||||||
|
request_builder() = default;
|
||||||
|
|
||||||
|
request_builder(request_builder&&) = default;
|
||||||
|
request_builder& operator=(request_builder&&) = default;
|
||||||
|
|
||||||
|
request_builder(const request_builder&) = delete;
|
||||||
|
request_builder& operator=(const request_builder&) = delete;
|
||||||
|
|
||||||
|
explicit request_builder(methods m) noexcept;
|
||||||
|
explicit request_builder(std::string u) noexcept;
|
||||||
|
explicit request_builder(methods m, std::string u) noexcept;
|
||||||
|
|
||||||
|
request_builder& url(std::string u) noexcept;
|
||||||
|
request_builder& method(methods m) noexcept;
|
||||||
|
request_builder& header(std::string key, std::string value);
|
||||||
|
|
||||||
|
request_builder& verbose(bool v) noexcept;
|
||||||
|
request_builder& verification(bool v) noexcept;
|
||||||
|
request_builder& redirections(std::uint32_t r) noexcept;
|
||||||
|
request_builder& response_timeout(time_sec_t t) noexcept;
|
||||||
|
request_builder& connection_timeout(time_sec_t t) noexcept;
|
||||||
|
|
||||||
|
request_builder& content(std::string_view b);
|
||||||
|
request_builder& content(content_t b) noexcept;
|
||||||
|
request_builder& uploader(uploader_uptr u) noexcept;
|
||||||
|
request_builder& downloader(downloader_uptr d) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& url() const noexcept;
|
||||||
|
[[nodiscard]] methods method() const noexcept;
|
||||||
|
[[nodiscard]] const headers_t& headers() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] bool verbose() const noexcept;
|
||||||
|
[[nodiscard]] bool verification() const noexcept;
|
||||||
|
[[nodiscard]] std::uint32_t redirections() const noexcept;
|
||||||
|
[[nodiscard]] time_sec_t response_timeout() const noexcept;
|
||||||
|
[[nodiscard]] time_sec_t connection_timeout() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] content_t& content() noexcept;
|
||||||
|
[[nodiscard]] const content_t& content() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] uploader_uptr& uploader() noexcept;
|
||||||
|
[[nodiscard]] const uploader_uptr& uploader() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] downloader_uptr& downloader() noexcept;
|
||||||
|
[[nodiscard]] const downloader_uptr& downloader() const noexcept;
|
||||||
|
private:
|
||||||
|
std::string url_;
|
||||||
|
methods method_{methods::get};
|
||||||
|
headers_t headers_;
|
||||||
|
bool verbose_{false};
|
||||||
|
bool verification_{true};
|
||||||
|
std::uint32_t redirections_{~0u};
|
||||||
|
time_sec_t response_timeout_{60u};
|
||||||
|
time_sec_t connection_timeout_{20u};
|
||||||
|
private:
|
||||||
|
content_t content_;
|
||||||
|
uploader_uptr uploader_;
|
||||||
|
downloader_uptr downloader_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace curly_hpp
|
||||||
|
{
|
||||||
class auto_updater {
|
class auto_updater {
|
||||||
public:
|
public:
|
||||||
auto_updater();
|
auto_updater();
|
||||||
~auto_updater() noexcept;
|
~auto_updater() noexcept;
|
||||||
|
|
||||||
ms_t wait_activity() const noexcept;
|
time_ms_t wait_activity() const noexcept;
|
||||||
void wait_activity(ms_t ms) noexcept;
|
void wait_activity(time_ms_t ms) noexcept;
|
||||||
private:
|
private:
|
||||||
std::thread thread_;
|
std::thread thread_;
|
||||||
ms_t wait_activity_{100};
|
time_ms_t wait_activity_{100};
|
||||||
std::atomic<bool> done_{false};
|
std::atomic<bool> done_{false};
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace curly_hpp
|
||||||
|
{
|
||||||
void update();
|
void update();
|
||||||
void wait_activity(ms_t ms);
|
void wait_activity(time_ms_t ms);
|
||||||
|
|
||||||
request perform(request_builder& rb);
|
request perform(request_builder& rb);
|
||||||
request perform(request_builder&& rb);
|
request perform(request_builder&& rb);
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ namespace
|
|||||||
CURL,
|
CURL,
|
||||||
void(*)(CURL*)>;
|
void(*)(CURL*)>;
|
||||||
|
|
||||||
using time_point_t = std::chrono::steady_clock::time_point;
|
|
||||||
using req_state_t = std::shared_ptr<request::internal_state>;
|
using req_state_t = std::shared_ptr<request::internal_state>;
|
||||||
std::map<CURL*, req_state_t> handles;
|
std::map<CURL*, req_state_t> handles;
|
||||||
|
|
||||||
@@ -130,13 +129,13 @@ namespace curly_hpp
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// case_insensitive_compare
|
// icase_compare
|
||||||
//
|
//
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace curly_hpp
|
namespace curly_hpp
|
||||||
{
|
{
|
||||||
bool case_insensitive_compare::operator()(
|
bool icase_compare::operator()(
|
||||||
const std::string& l,
|
const std::string& l,
|
||||||
const std::string& r) const noexcept
|
const std::string& r) const noexcept
|
||||||
{
|
{
|
||||||
@@ -150,136 +149,36 @@ namespace curly_hpp
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// request_builder
|
// content_t
|
||||||
//
|
//
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace curly_hpp
|
namespace curly_hpp
|
||||||
{
|
{
|
||||||
request_builder::request_builder(methods m) noexcept
|
content_t::content_t(std::string_view data)
|
||||||
: method_(m) {}
|
: data_(data.cbegin(), data.cend() ) {}
|
||||||
|
|
||||||
request_builder::request_builder(std::string u) noexcept
|
content_t::content_t(std::vector<char> data) noexcept
|
||||||
: url_(std::move(u)) {}
|
: data_(std::move(data)) {}
|
||||||
|
|
||||||
request_builder::request_builder(methods m, std::string u) noexcept
|
std::size_t content_t::size() const noexcept {
|
||||||
: url_(std::move(u))
|
return data_.size();
|
||||||
, method_(m) {}
|
|
||||||
|
|
||||||
request_builder& request_builder::url(std::string u) noexcept {
|
|
||||||
url_ = std::move(u);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request_builder& request_builder::method(methods m) noexcept {
|
std::vector<char>& content_t::data() noexcept {
|
||||||
method_ = m;
|
return data_;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request_builder& request_builder::header(std::string key, std::string value) {
|
const std::vector<char>& content_t::data() const noexcept {
|
||||||
headers_.insert_or_assign(std::move(key), std::move(value));
|
return data_;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request_builder& request_builder::verbose(bool v) noexcept {
|
std::string content_t::as_string_copy() const {
|
||||||
verbose_ = v;
|
return {data_.data(), data_.size()};
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request_builder& request_builder::verification(bool v) noexcept {
|
std::string_view content_t::as_string_view() const noexcept {
|
||||||
verification_ = v;
|
return {data_.data(), data_.size()};
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
request_builder& request_builder::response_timeout(sec_t t) noexcept {
|
|
||||||
response_timeout_ = t;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
request_builder& request_builder::connection_timeout(sec_t t) noexcept {
|
|
||||||
connection_timeout_ = t;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
request_builder& request_builder::redirections(std::uint32_t r) noexcept {
|
|
||||||
redirections_ = r;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
request_builder& request_builder::body(body_t b) noexcept {
|
|
||||||
body_ = std::move(b);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
request_builder& request_builder::body(std::string_view b) {
|
|
||||||
body_.assign(b.begin(), b.end());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
request_builder& request_builder::uploader(uploader_uptr u) noexcept {
|
|
||||||
uploader_ = std::move(u);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
request_builder& request_builder::downloader(downloader_uptr d) noexcept {
|
|
||||||
downloader_ = std::move(d);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& request_builder::url() const noexcept {
|
|
||||||
return url_;
|
|
||||||
}
|
|
||||||
|
|
||||||
methods request_builder::method() const noexcept {
|
|
||||||
return method_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const headers_t& request_builder::headers() const noexcept {
|
|
||||||
return headers_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool request_builder::verbose() const noexcept {
|
|
||||||
return verbose_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool request_builder::verification() const noexcept {
|
|
||||||
return verification_;
|
|
||||||
}
|
|
||||||
|
|
||||||
sec_t request_builder::response_timeout() const noexcept {
|
|
||||||
return response_timeout_;
|
|
||||||
}
|
|
||||||
|
|
||||||
sec_t request_builder::connection_timeout() const noexcept {
|
|
||||||
return connection_timeout_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint32_t request_builder::redirections() const noexcept {
|
|
||||||
return redirections_;
|
|
||||||
}
|
|
||||||
|
|
||||||
body_t& request_builder::body() noexcept {
|
|
||||||
return body_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const body_t& request_builder::body() const noexcept {
|
|
||||||
return body_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader_uptr& request_builder::uploader() noexcept {
|
|
||||||
return uploader_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uploader_uptr& request_builder::uploader() const noexcept {
|
|
||||||
return uploader_;
|
|
||||||
}
|
|
||||||
|
|
||||||
downloader_uptr& request_builder::downloader() noexcept {
|
|
||||||
return downloader_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const downloader_uptr& request_builder::downloader() const noexcept {
|
|
||||||
return downloader_;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,25 +188,43 @@ namespace curly_hpp
|
|||||||
//
|
//
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
response::response(response_code_t c, body_t b, headers_t h)
|
namespace curly_hpp
|
||||||
: code_(c)
|
{
|
||||||
, body_(std::move(b))
|
response::response(response_code_t rc) noexcept
|
||||||
, headers_(std::move(h)) {}
|
: code_(rc) {}
|
||||||
|
|
||||||
response_code_t response::code() const noexcept {
|
response::response(response_code_t rc, headers_t h) noexcept
|
||||||
return code_;
|
: code_(rc)
|
||||||
}
|
, headers_(std::move(h)) {}
|
||||||
|
|
||||||
const body_t& response::body() const noexcept {
|
response::response(response_code_t rc, content_t c) noexcept
|
||||||
return body_;
|
: code_(rc)
|
||||||
}
|
, content_(std::move(c)) {}
|
||||||
|
|
||||||
const headers_t& response::headers() const noexcept {
|
response::response(response_code_t rc, headers_t h, content_t c) noexcept
|
||||||
return headers_;
|
: code_(rc)
|
||||||
}
|
, headers_(std::move(h))
|
||||||
|
, content_(std::move(c)) {}
|
||||||
|
|
||||||
std::string_view response::body_as_string() const noexcept {
|
response_code_t response::code() const noexcept {
|
||||||
return {body_.data(), body_.size()};
|
return code_;
|
||||||
|
}
|
||||||
|
|
||||||
|
content_t& response::content() noexcept {
|
||||||
|
return content_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content_t& response::content() const noexcept {
|
||||||
|
return content_;
|
||||||
|
}
|
||||||
|
|
||||||
|
headers_t& response::headers() noexcept {
|
||||||
|
return headers_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers_t& response::headers() const noexcept {
|
||||||
|
return headers_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -323,7 +240,7 @@ namespace curly_hpp
|
|||||||
internal_state(handle_t handle, request_builder&& rb)
|
internal_state(handle_t handle, request_builder&& rb)
|
||||||
: hlist_(make_header_slist(rb.headers()))
|
: hlist_(make_header_slist(rb.headers()))
|
||||||
, handle_(std::move(handle))
|
, handle_(std::move(handle))
|
||||||
, body_(std::move(rb.body()))
|
, content_(std::move(rb.content()))
|
||||||
, uploader_(std::move(rb.uploader()))
|
, uploader_(std::move(rb.uploader()))
|
||||||
, downloader_(std::move(rb.downloader()))
|
, downloader_(std::move(rb.downloader()))
|
||||||
{
|
{
|
||||||
@@ -356,7 +273,7 @@ namespace curly_hpp
|
|||||||
curl_easy_setopt(handle_.get(), CURLOPT_UPLOAD, 1L);
|
curl_easy_setopt(handle_.get(), CURLOPT_UPLOAD, 1L);
|
||||||
curl_easy_setopt(handle_.get(), CURLOPT_INFILESIZE_LARGE, uploader_
|
curl_easy_setopt(handle_.get(), CURLOPT_INFILESIZE_LARGE, uploader_
|
||||||
? static_cast<curl_off_t>(uploader_->size())
|
? static_cast<curl_off_t>(uploader_->size())
|
||||||
: static_cast<curl_off_t>(body_.size()));
|
: static_cast<curl_off_t>(content_.size()));
|
||||||
break;
|
break;
|
||||||
case methods::get:
|
case methods::get:
|
||||||
curl_easy_setopt(handle_.get(), CURLOPT_HTTPGET, 1L);
|
curl_easy_setopt(handle_.get(), CURLOPT_HTTPGET, 1L);
|
||||||
@@ -368,7 +285,7 @@ namespace curly_hpp
|
|||||||
curl_easy_setopt(handle_.get(), CURLOPT_POST, 1L);
|
curl_easy_setopt(handle_.get(), CURLOPT_POST, 1L);
|
||||||
curl_easy_setopt(handle_.get(), CURLOPT_POSTFIELDSIZE_LARGE, uploader_
|
curl_easy_setopt(handle_.get(), CURLOPT_POSTFIELDSIZE_LARGE, uploader_
|
||||||
? static_cast<curl_off_t>(uploader_->size())
|
? static_cast<curl_off_t>(uploader_->size())
|
||||||
: static_cast<curl_off_t>(body_.size()));
|
: static_cast<curl_off_t>(content_.size()));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw exception("curly_hpp: unexpected request method");
|
throw exception("curly_hpp: unexpected request method");
|
||||||
@@ -390,10 +307,10 @@ namespace curly_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_setopt(handle_.get(), CURLOPT_CONNECTTIMEOUT,
|
curl_easy_setopt(handle_.get(), CURLOPT_CONNECTTIMEOUT,
|
||||||
std::max(sec_t(1), rb.connection_timeout()).count());
|
std::max(time_sec_t(1), rb.connection_timeout()).count());
|
||||||
|
|
||||||
last_response_ = time_point_t::clock::now();
|
last_response_ = time_point_t::clock::now();
|
||||||
response_timeout_ = std::max(sec_t(1), rb.response_timeout());
|
response_timeout_ = std::max(time_sec_t(1), rb.response_timeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool done() noexcept {
|
bool done() noexcept {
|
||||||
@@ -410,8 +327,8 @@ namespace curly_hpp
|
|||||||
|
|
||||||
response_ = response(
|
response_ = response(
|
||||||
static_cast<response_code_t>(response_code),
|
static_cast<response_code_t>(response_code),
|
||||||
std::move(response_body_),
|
std::move(response_headers_),
|
||||||
std::move(response_headers_));
|
std::move(response_content_));
|
||||||
|
|
||||||
status_ = statuses::done;
|
status_ = statuses::done;
|
||||||
error_.clear();
|
error_.clear();
|
||||||
@@ -528,8 +445,8 @@ namespace curly_hpp
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
std::lock_guard<std::mutex> guard(mutex_);
|
||||||
size = std::min(size, body_.size() - uploaded_.load());
|
size = std::min(size, content_.size() - uploaded_.load());
|
||||||
std::memcpy(dst, body_.data() + uploaded_.load(), size);
|
std::memcpy(dst, content_.data().data() + uploaded_.load(), size);
|
||||||
uploaded_.fetch_add(size);
|
uploaded_.fetch_add(size);
|
||||||
return size;
|
return size;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -544,7 +461,7 @@ namespace curly_hpp
|
|||||||
downloaded_.fetch_add(bytes);
|
downloaded_.fetch_add(bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
response_body_.insert(response_body_.end(), src, src + size);
|
response_content_.insert(response_content_.end(), src, src + size);
|
||||||
downloaded_.fetch_add(size);
|
downloaded_.fetch_add(size);
|
||||||
return size;
|
return size;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -578,22 +495,24 @@ namespace curly_hpp
|
|||||||
private:
|
private:
|
||||||
slist_t hlist_;
|
slist_t hlist_;
|
||||||
handle_t handle_;
|
handle_t handle_;
|
||||||
body_t body_;
|
content_t content_;
|
||||||
uploader_uptr uploader_;
|
uploader_uptr uploader_;
|
||||||
downloader_uptr downloader_;
|
downloader_uptr downloader_;
|
||||||
private:
|
private:
|
||||||
time_point_t last_response_;
|
time_point_t last_response_;
|
||||||
time_point_t::duration response_timeout_;
|
time_point_t::duration response_timeout_;
|
||||||
private:
|
private:
|
||||||
mutable std::mutex mutex_;
|
|
||||||
mutable std::condition_variable cond_var_;
|
|
||||||
response response_;
|
response response_;
|
||||||
body_t response_body_;
|
|
||||||
headers_t response_headers_;
|
headers_t response_headers_;
|
||||||
|
std::vector<char> response_content_;
|
||||||
|
private:
|
||||||
std::atomic_size_t uploaded_{0u};
|
std::atomic_size_t uploaded_{0u};
|
||||||
std::atomic_size_t downloaded_{0u};
|
std::atomic_size_t downloaded_{0u};
|
||||||
statuses status_{statuses::pending};
|
statuses status_{statuses::pending};
|
||||||
std::string error_{"Unknown error"};
|
std::string error_{"Unknown error"};
|
||||||
|
private:
|
||||||
|
mutable std::mutex mutex_;
|
||||||
|
mutable std::condition_variable cond_var_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,6 +542,141 @@ namespace curly_hpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// request_builder
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace curly_hpp
|
||||||
|
{
|
||||||
|
request_builder::request_builder(methods m) noexcept
|
||||||
|
: method_(m) {}
|
||||||
|
|
||||||
|
request_builder::request_builder(std::string u) noexcept
|
||||||
|
: url_(std::move(u)) {}
|
||||||
|
|
||||||
|
request_builder::request_builder(methods m, std::string u) noexcept
|
||||||
|
: url_(std::move(u))
|
||||||
|
, method_(m) {}
|
||||||
|
|
||||||
|
request_builder& request_builder::url(std::string u) noexcept {
|
||||||
|
url_ = std::move(u);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::method(methods m) noexcept {
|
||||||
|
method_ = m;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::header(std::string key, std::string value) {
|
||||||
|
headers_.insert_or_assign(std::move(key), std::move(value));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::verbose(bool v) noexcept {
|
||||||
|
verbose_ = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::verification(bool v) noexcept {
|
||||||
|
verification_ = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::redirections(std::uint32_t r) noexcept {
|
||||||
|
redirections_ = r;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::response_timeout(time_sec_t t) noexcept {
|
||||||
|
response_timeout_ = t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::connection_timeout(time_sec_t t) noexcept {
|
||||||
|
connection_timeout_ = t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::content(std::string_view c) {
|
||||||
|
content_ = content_t(c);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::content(content_t c) noexcept {
|
||||||
|
content_ = std::move(c);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::uploader(uploader_uptr u) noexcept {
|
||||||
|
uploader_ = std::move(u);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_builder& request_builder::downloader(downloader_uptr d) noexcept {
|
||||||
|
downloader_ = std::move(d);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& request_builder::url() const noexcept {
|
||||||
|
return url_;
|
||||||
|
}
|
||||||
|
|
||||||
|
methods request_builder::method() const noexcept {
|
||||||
|
return method_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers_t& request_builder::headers() const noexcept {
|
||||||
|
return headers_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool request_builder::verbose() const noexcept {
|
||||||
|
return verbose_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool request_builder::verification() const noexcept {
|
||||||
|
return verification_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t request_builder::redirections() const noexcept {
|
||||||
|
return redirections_;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_sec_t request_builder::response_timeout() const noexcept {
|
||||||
|
return response_timeout_;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_sec_t request_builder::connection_timeout() const noexcept {
|
||||||
|
return connection_timeout_;
|
||||||
|
}
|
||||||
|
|
||||||
|
content_t& request_builder::content() noexcept {
|
||||||
|
return content_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content_t& request_builder::content() const noexcept {
|
||||||
|
return content_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uploader_uptr& request_builder::uploader() noexcept {
|
||||||
|
return uploader_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploader_uptr& request_builder::uploader() const noexcept {
|
||||||
|
return uploader_;
|
||||||
|
}
|
||||||
|
|
||||||
|
downloader_uptr& request_builder::downloader() noexcept {
|
||||||
|
return downloader_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloader_uptr& request_builder::downloader() const noexcept {
|
||||||
|
return downloader_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// auto_updater
|
// auto_updater
|
||||||
@@ -647,11 +701,11 @@ namespace curly_hpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ms_t auto_updater::wait_activity() const noexcept {
|
time_ms_t auto_updater::wait_activity() const noexcept {
|
||||||
return wait_activity_;
|
return wait_activity_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void auto_updater::wait_activity(ms_t ms) noexcept {
|
void auto_updater::wait_activity(time_ms_t ms) noexcept {
|
||||||
wait_activity_ = ms;
|
wait_activity_ = ms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -704,7 +758,7 @@ namespace curly_hpp
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait_activity(ms_t ms) {
|
void wait_activity(time_ms_t ms) {
|
||||||
curl_state::with([ms](CURLM* curlm){
|
curl_state::with([ms](CURLM* curlm){
|
||||||
curl_multi_wait(curlm, nullptr, 0, static_cast<int>(ms.count()), nullptr);
|
curl_multi_wait(curlm, nullptr, 0, static_cast<int>(ms.count()), nullptr);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ TEST_CASE("curly"){
|
|||||||
{
|
{
|
||||||
auto req = net::perform(net::request_builder()
|
auto req = net::perform(net::request_builder()
|
||||||
.url("https://httpbin.org/delay/2")
|
.url("https://httpbin.org/delay/2")
|
||||||
.response_timeout(net::sec_t(0)));
|
.response_timeout(net::time_sec_t(0)));
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -205,9 +205,9 @@ TEST_CASE("curly"){
|
|||||||
.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"));
|
||||||
const auto resp = req.get();
|
const auto resp = req.get();
|
||||||
const auto body_j = json::parse(resp.body_as_string());
|
const auto content_j = json::parse(resp.content().as_string_view());
|
||||||
REQUIRE(body_j["headers"]["Custom-Header-1"] == "custom_header_value_1");
|
REQUIRE(content_j["headers"]["Custom-Header-1"] == "custom_header_value_1");
|
||||||
REQUIRE(body_j["headers"]["Custom-Header-2"] == "custom header value 2");
|
REQUIRE(content_j["headers"]["Custom-Header-2"] == "custom header value 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("response_inspection") {
|
SECTION("response_inspection") {
|
||||||
@@ -215,18 +215,18 @@ TEST_CASE("curly"){
|
|||||||
auto req = net::perform(net::request_builder()
|
auto req = net::perform(net::request_builder()
|
||||||
.url("https://httpbin.org/response-headers?hello=world&world=hello"));
|
.url("https://httpbin.org/response-headers?hello=world&world=hello"));
|
||||||
const auto resp = req.get();
|
const auto resp = req.get();
|
||||||
const auto body_j = json::parse(resp.body_as_string());
|
const auto content_j = json::parse(resp.content().as_string_view());
|
||||||
REQUIRE(body_j["hello"] == "world");
|
REQUIRE(content_j["hello"] == "world");
|
||||||
REQUIRE(body_j["world"] == "hello");
|
REQUIRE(content_j["world"] == "hello");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto req = net::perform(net::request_builder()
|
auto req = net::perform(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));
|
||||||
const auto resp = req.get();
|
const auto resp = req.get();
|
||||||
const auto body_j = json::parse(resp.body_as_string());
|
const auto content_j = json::parse(resp.content().as_string_view());
|
||||||
REQUIRE(body_j["hello"] == "world");
|
REQUIRE(content_j["hello"] == "world");
|
||||||
REQUIRE(body_j["world"] == "hello");
|
REQUIRE(content_j["world"] == "hello");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,20 +235,20 @@ TEST_CASE("curly"){
|
|||||||
auto req = net::perform(net::request_builder()
|
auto req = net::perform(net::request_builder()
|
||||||
.url("https://httpbin.org/base64/SFRUUEJJTiBpcyBhd2Vzb21l"));
|
.url("https://httpbin.org/base64/SFRUUEJJTiBpcyBhd2Vzb21l"));
|
||||||
const auto resp = req.get();
|
const auto resp = req.get();
|
||||||
REQUIRE(resp.body_as_string() == "HTTPBIN is awesome");
|
REQUIRE(resp.content().as_string_view() == "HTTPBIN is awesome");
|
||||||
REQUIRE(req.error().empty());
|
REQUIRE(req.error().empty());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto req = net::perform(net::request_builder()
|
auto req = net::perform(net::request_builder()
|
||||||
.url("https://httpbin.org/delay/10")
|
.url("https://httpbin.org/delay/10")
|
||||||
.response_timeout(net::sec_t(0)));
|
.response_timeout(net::time_sec_t(0)));
|
||||||
REQUIRE(req.wait() == net::request::statuses::timeout);
|
REQUIRE(req.wait() == net::request::statuses::timeout);
|
||||||
REQUIRE_FALSE(req.error().empty());
|
REQUIRE_FALSE(req.error().empty());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto req = net::perform(net::request_builder()
|
auto req = net::perform(net::request_builder()
|
||||||
.url("https://httpbin.org/delay/10")
|
.url("https://httpbin.org/delay/10")
|
||||||
.response_timeout(net::sec_t(1)));
|
.response_timeout(net::time_sec_t(1)));
|
||||||
REQUIRE(req.wait() == net::request::statuses::timeout);
|
REQUIRE(req.wait() == net::request::statuses::timeout);
|
||||||
REQUIRE_FALSE(req.error().empty());
|
REQUIRE_FALSE(req.error().empty());
|
||||||
}
|
}
|
||||||
@@ -263,9 +263,9 @@ TEST_CASE("curly"){
|
|||||||
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");
|
||||||
REQUIRE(untests::png_data_length == resp.body().size());
|
REQUIRE(untests::png_data_length == resp.content().size());
|
||||||
REQUIRE(!std::memcmp(
|
REQUIRE(!std::memcmp(
|
||||||
resp.body().data(),
|
resp.content().data().data(),
|
||||||
untests::png_data,
|
untests::png_data,
|
||||||
untests::png_data_length));
|
untests::png_data_length));
|
||||||
}
|
}
|
||||||
@@ -277,9 +277,9 @@ TEST_CASE("curly"){
|
|||||||
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");
|
||||||
REQUIRE(untests::jpeg_data_length == resp.body().size());
|
REQUIRE(untests::jpeg_data_length == resp.content().size());
|
||||||
REQUIRE(!std::memcmp(
|
REQUIRE(!std::memcmp(
|
||||||
resp.body().data(),
|
resp.content().data().data(),
|
||||||
untests::jpeg_data,
|
untests::jpeg_data,
|
||||||
untests::jpeg_data_length));
|
untests::jpeg_data_length));
|
||||||
}
|
}
|
||||||
@@ -312,31 +312,31 @@ TEST_CASE("curly"){
|
|||||||
.url("https://httpbin.org/anything")
|
.url("https://httpbin.org/anything")
|
||||||
.method(net::methods::put)
|
.method(net::methods::put)
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.body(R"({"hello":"world"})"));
|
.content(R"({"hello":"world"})"));
|
||||||
const auto resp = req.get();
|
const auto resp = req.get();
|
||||||
const auto body_j = json::parse(resp.body_as_string());
|
const auto content_j = json::parse(resp.content().as_string_view());
|
||||||
REQUIRE(body_j["data"] == R"({"hello":"world"})");
|
REQUIRE(content_j["data"] == R"({"hello":"world"})");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto req = net::perform(net::request_builder()
|
auto req = net::perform(net::request_builder()
|
||||||
.url("https://httpbin.org/anything")
|
.url("https://httpbin.org/anything")
|
||||||
.method(net::methods::post)
|
.method(net::methods::post)
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.body(R"({"hello":"world"})"));
|
.content(R"({"hello":"world"})"));
|
||||||
const auto resp = req.get();
|
const auto resp = req.get();
|
||||||
const auto body_j = json::parse(resp.body_as_string());
|
const auto content_j = json::parse(resp.content().as_string_view());
|
||||||
REQUIRE(body_j["data"] == R"({"hello":"world"})");
|
REQUIRE(content_j["data"] == R"({"hello":"world"})");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto req = net::perform(net::request_builder()
|
auto req = net::perform(net::request_builder()
|
||||||
.url("https://httpbin.org/anything")
|
.url("https://httpbin.org/anything")
|
||||||
.method(net::methods::post)
|
.method(net::methods::post)
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
.body("hello=world&world=hello"));
|
.content("hello=world&world=hello"));
|
||||||
const auto resp = req.get();
|
const auto resp = req.get();
|
||||||
const auto body_j = json::parse(resp.body_as_string());
|
const auto content_j = json::parse(resp.content().as_string_view());
|
||||||
REQUIRE(body_j["form"]["hello"] == "world");
|
REQUIRE(content_j["form"]["hello"] == "world");
|
||||||
REQUIRE(body_j["form"]["world"] == "hello");
|
REQUIRE(content_j["form"]["world"] == "hello");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user