mirror of
https://github.com/BlackMATov/curly.hpp.git
synced 2025-12-16 14:11:17 +07:00
more safety handlers
This commit is contained in:
14
README.md
14
README.md
@@ -151,7 +151,7 @@ public:
|
||||
file_dowloader(const char* filename)
|
||||
: stream_(filename, std::ofstream::binary) {}
|
||||
|
||||
std::size_t download(const char* src, std::size_t size) override {
|
||||
std::size_t write(const char* src, std::size_t size) override {
|
||||
stream_.write(src, size);
|
||||
return size;
|
||||
}
|
||||
@@ -173,23 +173,21 @@ public:
|
||||
file_uploader(const char* filename)
|
||||
: stream_(filename, std::ifstream::binary) {
|
||||
stream_.seekg(0, std::ios::end);
|
||||
available_ = static_cast<std::size_t>(stream_.tellg());
|
||||
size_ = static_cast<std::size_t>(stream_.tellg());
|
||||
stream_.seekg(0, std::ios::beg);
|
||||
}
|
||||
|
||||
std::size_t size() const override {
|
||||
return available_;
|
||||
return size_;
|
||||
}
|
||||
|
||||
std::size_t upload(char* dst, std::size_t size) override {
|
||||
std::size_t read_bytes = std::min(size, available_);
|
||||
stream_.read(dst, read_bytes);
|
||||
available_ -= read_bytes;
|
||||
return read_bytes;
|
||||
stream_.read(dst, size);
|
||||
return size;
|
||||
}
|
||||
private:
|
||||
std::size_t size_{0u};
|
||||
std::ifstream stream_;
|
||||
std::size_t available_{0u};
|
||||
};
|
||||
|
||||
net::request_builder()
|
||||
|
||||
@@ -52,13 +52,13 @@ namespace curly_hpp
|
||||
public:
|
||||
virtual ~upload_handler() {}
|
||||
virtual std::size_t size() const = 0;
|
||||
virtual std::size_t upload(char* dst, std::size_t size) = 0;
|
||||
virtual std::size_t read(char* dst, std::size_t size) = 0;
|
||||
};
|
||||
|
||||
class download_handler {
|
||||
public:
|
||||
virtual ~download_handler() {}
|
||||
virtual std::size_t download(const char* src, std::size_t size) = 0;
|
||||
virtual std::size_t write(const char* src, std::size_t size) = 0;
|
||||
};
|
||||
|
||||
using uploader_uptr = std::unique_ptr<upload_handler>;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <curly.hpp/curly.hpp>
|
||||
|
||||
#include <cctype>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include <mutex>
|
||||
@@ -52,7 +53,11 @@ namespace
|
||||
} else {
|
||||
header_builder.append(";");
|
||||
}
|
||||
result = curl_slist_append(result, header_builder.c_str());
|
||||
curl_slist* tmp_result = curl_slist_append(result, header_builder.c_str());
|
||||
if ( !tmp_result ) {
|
||||
throw exception("curly_hpp: failed to curl_slist_append");
|
||||
}
|
||||
result = tmp_result;
|
||||
} catch (...) {
|
||||
curl_slist_free_all(result);
|
||||
throw;
|
||||
@@ -72,8 +77,8 @@ namespace
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
std::size_t upload(char* dst, std::size_t size) override {
|
||||
size = std::min(size, data_.size() - uploaded_);
|
||||
std::size_t read(char* dst, std::size_t size) override {
|
||||
assert(size <= data_.size() - uploaded_);
|
||||
std::memcpy(dst, data_.data() + uploaded_, size);
|
||||
uploaded_ += size;
|
||||
return size;
|
||||
@@ -90,7 +95,7 @@ namespace
|
||||
default_downloader(data_t* dst) noexcept
|
||||
: data_(*dst) {}
|
||||
|
||||
std::size_t download(const char* src, std::size_t size) override {
|
||||
std::size_t write(const char* src, std::size_t size) override {
|
||||
data_.insert(data_.end(), src, src + size);
|
||||
return size;
|
||||
}
|
||||
@@ -112,7 +117,9 @@ namespace
|
||||
class curl_state {
|
||||
public:
|
||||
template < typename F >
|
||||
static std::invoke_result_t<F, CURLM*> with(F&& f) {
|
||||
static std::invoke_result_t<F, CURLM*> with(F&& f)
|
||||
noexcept(std::is_nothrow_invocable_v<F, CURLM*>)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
if ( !self_ ) {
|
||||
self_ = std::make_unique<curl_state>();
|
||||
@@ -496,7 +503,10 @@ namespace curly_hpp
|
||||
|
||||
std::size_t upload_callback_(char* dst, std::size_t size) noexcept {
|
||||
try {
|
||||
return uploader_->upload(dst, size);
|
||||
size = std::min(size, uploader_->size() - uploaded_.load());
|
||||
const std::size_t read_bytes = uploader_->read(dst, size);
|
||||
uploaded_.fetch_add(read_bytes);
|
||||
return read_bytes;
|
||||
} catch (...) {
|
||||
return CURL_READFUNC_ABORT;
|
||||
}
|
||||
@@ -504,7 +514,9 @@ namespace curly_hpp
|
||||
|
||||
std::size_t download_callback_(const char* src, std::size_t size) noexcept {
|
||||
try {
|
||||
return downloader_->download(src, size);
|
||||
const std::size_t written_bytes = downloader_->write(src, size);
|
||||
downloaded_.fetch_add(written_bytes);
|
||||
return written_bytes;
|
||||
} catch (...) {
|
||||
return 0u;
|
||||
}
|
||||
@@ -546,6 +558,9 @@ namespace curly_hpp
|
||||
response response_;
|
||||
headers_t response_headers_;
|
||||
std::vector<char> response_content_;
|
||||
private:
|
||||
std::atomic_size_t uploaded_{0u};
|
||||
std::atomic_size_t downloaded_{0u};
|
||||
private:
|
||||
statuses status_{statuses::pending};
|
||||
std::string error_{"Unknown error"};
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t upload(char* dst, std::size_t size) override {
|
||||
std::size_t read(char* dst, std::size_t size) override {
|
||||
(void)dst;
|
||||
std::cout << "---------- ** UPLOAD (" << size << ") ** ---------- " << std::endl;
|
||||
return size;
|
||||
@@ -40,7 +40,7 @@ namespace
|
||||
public:
|
||||
verbose_downloader() = default;
|
||||
|
||||
std::size_t download(const char* src, std::size_t size) override {
|
||||
std::size_t write(const char* src, std::size_t size) override {
|
||||
(void)src;
|
||||
std::cout << "---------- ** DOWNLOAD (" << size << ") ** ---------- " << std::endl;
|
||||
return size;
|
||||
@@ -452,7 +452,7 @@ TEST_CASE("curly_examples") {
|
||||
file_dowloader(const char* filename)
|
||||
: stream_(filename, std::ofstream::binary) {}
|
||||
|
||||
std::size_t download(const char* src, std::size_t size) override {
|
||||
std::size_t write(const char* src, std::size_t size) override {
|
||||
stream_.write(src, size);
|
||||
return size;
|
||||
}
|
||||
@@ -463,7 +463,7 @@ TEST_CASE("curly_examples") {
|
||||
net::request_builder()
|
||||
.url("https://httpbin.org/image/jpeg")
|
||||
.downloader<file_dowloader>("image.jpeg")
|
||||
.send().wait();
|
||||
.send().get();
|
||||
}
|
||||
{
|
||||
class file_uploader : public net::upload_handler {
|
||||
@@ -471,30 +471,28 @@ TEST_CASE("curly_examples") {
|
||||
file_uploader(const char* filename)
|
||||
: stream_(filename, std::ifstream::binary) {
|
||||
stream_.seekg(0, std::ios::end);
|
||||
available_ = static_cast<std::size_t>(stream_.tellg());
|
||||
size_ = static_cast<std::size_t>(stream_.tellg());
|
||||
stream_.seekg(0, std::ios::beg);
|
||||
}
|
||||
|
||||
std::size_t size() const override {
|
||||
return available_;
|
||||
return size_;
|
||||
}
|
||||
|
||||
std::size_t upload(char* dst, std::size_t size) override {
|
||||
std::size_t read_bytes = std::min(size, available_);
|
||||
stream_.read(dst, read_bytes);
|
||||
available_ -= read_bytes;
|
||||
return read_bytes;
|
||||
std::size_t read(char* dst, std::size_t size) override {
|
||||
stream_.read(dst, size);
|
||||
return size;
|
||||
}
|
||||
private:
|
||||
std::size_t size_{0u};
|
||||
std::ifstream stream_;
|
||||
std::size_t available_{0u};
|
||||
};
|
||||
|
||||
net::request_builder()
|
||||
.method(net::methods::post)
|
||||
.url("https://httpbin.org/anything")
|
||||
.uploader<file_uploader>("image.jpeg")
|
||||
.send().wait();
|
||||
.send().get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user