summaryrefslogtreecommitdiff
path: root/src/http.cpp
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2022-08-12 18:35:58 -0400
committerouwou <26526779+ouwou@users.noreply.github.com>2022-08-12 18:35:58 -0400
commit6a5ecb4d9584f7276cf1d592c95811a66943f61c (patch)
tree2c09268db37461ce9e1882789183c508bb36dd4a /src/http.cpp
parentdc28eae95a46c3079fcc76b3425ffa37844dd37d (diff)
parentf60cea2216dd9677cb9105364cdaa778a0c187db (diff)
downloadabaddon-portaudio-6a5ecb4d9584f7276cf1d592c95811a66943f61c.tar.gz
abaddon-portaudio-6a5ecb4d9584f7276cf1d592c95811a66943f61c.zip
Merge branch 'attachments'
Diffstat (limited to 'src/http.cpp')
-rw-r--r--src/http.cpp81
1 files changed, 80 insertions, 1 deletions
diff --git a/src/http.cpp b/src/http.cpp
index 80fb829..0fae39f 100644
--- a/src/http.cpp
+++ b/src/http.cpp
@@ -29,12 +29,53 @@ request::request(EMethod method, std::string url)
prepare();
}
+request::request(request &&other) noexcept
+ : m_curl(std::exchange(other.m_curl, nullptr))
+ , m_url(std::exchange(other.m_url, ""))
+ , m_method(std::exchange(other.m_method, nullptr))
+ , m_header_list(std::exchange(other.m_header_list, nullptr))
+ , m_error_buf(other.m_error_buf)
+ , m_form(std::exchange(other.m_form, nullptr))
+ , m_read_streams(std::move(other.m_read_streams))
+ , m_progress_callback(std::move(other.m_progress_callback)) {
+ if (m_progress_callback) {
+ curl_easy_setopt(m_curl, CURLOPT_XFERINFODATA, this);
+ }
+}
+
request::~request() {
if (m_curl != nullptr)
curl_easy_cleanup(m_curl);
if (m_header_list != nullptr)
curl_slist_free_all(m_header_list);
+
+ if (m_form != nullptr)
+ curl_mime_free(m_form);
+}
+
+const std::string &request::get_url() const {
+ return m_url;
+}
+
+const char *request::get_method() const {
+ return m_method;
+}
+
+size_t http_req_xferinfofunc(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) {
+ if (ultotal > 0) {
+ auto *req = reinterpret_cast<request *>(clientp);
+ req->m_progress_callback(ultotal, ulnow);
+ }
+
+ return 0;
+}
+
+void request::set_progress_callback(std::function<void(curl_off_t, curl_off_t)> func) {
+ m_progress_callback = std::move(func);
+ curl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 0L);
+ curl_easy_setopt(m_curl, CURLOPT_XFERINFOFUNCTION, http_req_xferinfofunc);
+ curl_easy_setopt(m_curl, CURLOPT_XFERINFODATA, this);
}
void request::set_verify_ssl(bool verify) {
@@ -61,6 +102,42 @@ CURL *request::get_curl() {
return m_curl;
}
+void request::make_form() {
+ m_form = curl_mime_init(m_curl);
+}
+
+static size_t http_readfunc(char *buffer, size_t size, size_t nitems, void *arg) {
+ auto stream = Glib::wrap(G_FILE_INPUT_STREAM(arg), true);
+ int r = stream->read(buffer, size * nitems);
+ if (r == -1) {
+ // https://github.com/curl/curl/blob/ad9bc5976d6661cd5b03ebc379313bf657701c14/lib/mime.c#L724
+ return size_t(-1);
+ }
+ return r;
+}
+
+// file must exist until request completes
+void request::add_file(std::string_view name, const Glib::RefPtr<Gio::File> &file, std::string_view filename) {
+ if (!file->query_exists()) return;
+
+ auto *field = curl_mime_addpart(m_form);
+ curl_mime_name(field, name.data());
+ auto info = file->query_info();
+ auto stream = file->read();
+ curl_mime_data_cb(field, info->get_size(), http_readfunc, nullptr, nullptr, stream->gobj());
+ curl_mime_filename(field, filename.data());
+
+ // hold ref
+ m_read_streams.insert(stream);
+}
+
+// copied
+void request::add_field(std::string_view name, const char *data, size_t size) {
+ auto *field = curl_mime_addpart(m_form);
+ curl_mime_name(field, name.data());
+ curl_mime_data(field, data, size);
+}
+
response request::execute() {
if (m_curl == nullptr) {
auto response = detail::make_response(m_url, EStatusCode::ClientErrorCURLInit);
@@ -80,12 +157,14 @@ response request::execute() {
m_error_buf[0] = '\0';
if (m_header_list != nullptr)
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_header_list);
+ if (m_form != nullptr)
+ curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, m_form);
CURLcode result = curl_easy_perform(m_curl);
if (result != CURLE_OK) {
auto response = detail::make_response(m_url, EStatusCode::ClientErrorCURLPerform);
response.error_string = curl_easy_strerror(result);
- response.error_string += " " + std::string(m_error_buf);
+ response.error_string += " " + std::string(m_error_buf.data());
return response;
}