more safety handlers

This commit is contained in:
2019-06-26 10:16:14 +07:00
parent 38fd73a08a
commit 49c436ac83
4 changed files with 41 additions and 30 deletions

View File

@@ -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()

View File

@@ -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>;

View File

@@ -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"};

View File

@@ -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();
}
}
}