summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortastytea2020-01-10 13:08:34 +0100
committertastytea2020-01-10 13:08:34 +0100
commitf2222151169419fe3afbcdfa3c4ec53627ab1021 (patch)
treec7f625a54d60286fb08e7848207d2f67966117bd
parent529e4bca6dcc7a5478c8247e2917f4905d8835b9 (diff)
downloadmastodonpp-f2222151169419fe3afbcdfa3c4ec53627ab1021.tar
mastodonpp-f2222151169419fe3afbcdfa3c4ec53627ab1021.tar.gz
mastodonpp-f2222151169419fe3afbcdfa3c4ec53627ab1021.zip
Implement HTTP POST in CURLWrapper.
-rw-r--r--cmake/mastodonppConfig.cmake.in2
-rw-r--r--include/curl_wrapper.hpp29
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/curl_wrapper.cpp106
4 files changed, 121 insertions, 18 deletions
diff --git a/cmake/mastodonppConfig.cmake.in b/cmake/mastodonppConfig.cmake.in
index 4dbde82..e703c6a 100644
--- a/cmake/mastodonppConfig.cmake.in
+++ b/cmake/mastodonppConfig.cmake.in
@@ -1,5 +1,5 @@
include(CMakeFindDependencyMacro)
-find_dependency(CURL 7.32 REQUIRED)
+find_dependency(CURL 7.56 REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
diff --git a/include/curl_wrapper.hpp b/include/curl_wrapper.hpp
index f4da6ff..0daf771 100644
--- a/include/curl_wrapper.hpp
+++ b/include/curl_wrapper.hpp
@@ -264,6 +264,18 @@ private:
void setup_curl();
/*!
+ * @brief Replace parameter in URI.
+ *
+ * @param uri Reference to the URI.
+ * @param parameter The parameter.
+ *
+ * @return true if parameter was replaced.
+ *
+ * @since 0.1.0
+ */
+ bool replace_parameter_in_uri(string &uri, const parameterpair &parameter);
+
+ /*!
* @brief Add parameters to URI.
*
* @param uri Reference to the URI.
@@ -272,6 +284,23 @@ private:
* @since 0.1.0
*/
void add_parameters_to_uri(string &uri, const parametermap &parameters);
+
+ /*!
+ * @brief Convert parametermap to `*curl_mime`.
+ *
+ * For more information consult [curl_mime_init(3)]
+ * (https://curl.haxx.se/libcurl/c/curl_mime_init.html). Calls
+ * replace_parameter_in_uri().
+ *
+ * @param uri Reference to the URI.
+ * @param parameters The parametermap.
+ *
+ * @return `*curl_mime`.
+ *
+ * @since 0.1.0
+ */
+ curl_mime *parameters_to_curl_mime(string &uri,
+ const parametermap &parameters);
};
} // namespace mastodonpp
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b9ede8d..a7c16ef 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,6 @@
include(GNUInstallDirs)
-find_package(CURL 7.32 REQUIRED)
+find_package(CURL 7.56 REQUIRED)
# Write version in header.
configure_file ("version.hpp.in"
diff --git a/src/curl_wrapper.cpp b/src/curl_wrapper.cpp
index f675cca..6746fe1 100644
--- a/src/curl_wrapper.cpp
+++ b/src/curl_wrapper.cpp
@@ -68,7 +68,7 @@ CURLWrapper::~CURLWrapper() noexcept
void CURLWrapper::set_proxy(const string_view proxy)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
- CURLcode code = curl_easy_setopt(_connection, CURLOPT_PROXY, proxy);
+ CURLcode code{curl_easy_setopt(_connection, CURLOPT_PROXY, proxy)};
if (code != CURLE_OK)
{
throw CURLException{code, "Failed to set proxy", _curl_buffer_error};
@@ -101,8 +101,11 @@ answer_type CURLWrapper::make_request(const http_method &method, string uri,
}
case http_method::POST:
{
+ curl_mime *mime{parameters_to_curl_mime(uri, parameters)};
+
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
- code = curl_easy_setopt(_connection, CURLOPT_POST, 1L);
+ code = curl_easy_setopt(_connection, CURLOPT_MIMEPOST, mime);
+
break;
}
case http_method::PATCH:
@@ -247,27 +250,38 @@ void CURLWrapper::setup_curl()
curl_easy_setopt(_connection, CURLOPT_MAXREDIRS, 10L);
}
+bool CURLWrapper::replace_parameter_in_uri(string &uri,
+ const parameterpair &parameter)
+{
+ static constexpr array replace
+ {
+ "id", "nickname", "nickname_or_id",
+ "hashtag", "permission_group"
+ };
+ if (any_of(replace.begin(), replace.end(),
+ [&parameter](const auto &s) { return s == parameter.first; }))
+ {
+ const auto pos{uri.find('<')};
+ if (pos != string::npos)
+ {
+ uri.replace(pos, parameter.first.size() + 2,
+ get<string_view>(parameter.second));
+ return true;
+ }
+ }
+
+ return false;
+}
+
void CURLWrapper::add_parameters_to_uri(string &uri,
const parametermap &parameters)
{
// Replace <ID> with the value of parameter “id” and so on.
for (const auto &param : parameters)
{
- static constexpr array replace_in_uri
- {
- "id", "nickname", "nickname_or_id",
- "hashtag", "permission_group"
- };
- if (any_of(replace_in_uri.begin(), replace_in_uri.end(),
- [&param](const auto &s) { return s == param.first; }))
+ if (replace_parameter_in_uri(uri, param))
{
- const auto pos{uri.find('<')};
- if (pos != string::npos)
- {
- uri.replace(pos, param.first.size() + 2,
- get<string_view>(param.second));
- continue;
- }
+ continue;
}
static bool first{true};
@@ -298,4 +312,64 @@ void CURLWrapper::add_parameters_to_uri(string &uri,
}
}
+curl_mime *CURLWrapper::parameters_to_curl_mime(string &uri,
+ const parametermap &parameters)
+{
+ debuglog << "Building HTTP form.\n";
+
+ curl_mime *mime{curl_mime_init(_connection)};
+ for (const auto &param : parameters)
+ {
+ if (replace_parameter_in_uri(uri, param))
+ {
+ continue;
+ }
+
+ curl_mimepart *part{curl_mime_addpart(mime)};
+ if (part == nullptr)
+ {
+ throw CURLException{"Could not build HTTP form."};
+ }
+
+ CURLcode code;
+ if (holds_alternative<string_view>(param.second))
+ {
+ code = curl_mime_name(part, param.first.data());
+ if (code != CURLE_OK)
+ {
+ throw CURLException{code, "Could not build HTTP form."};
+ }
+
+ code = curl_mime_data(part, get<string_view>(param.second).data(),
+ CURL_ZERO_TERMINATED);
+ if (code != CURLE_OK)
+ {
+ throw CURLException{code, "Could not build HTTP form."};
+ }
+ debuglog << "Set form part: " << param.first << " = "
+ << get<string_view>(param.second) << '\n';
+ }
+ else
+ {
+ for (const auto &arg : get<vector<string_view>>(param.second))
+ {
+ const string name{string(param.first) += "[]"};
+ code = curl_mime_name(part, name.c_str());
+ if (code != CURLE_OK)
+ {
+ throw CURLException{code, "Could not build HTTP form."};
+ }
+ code = curl_mime_data(part, arg.data(), CURL_ZERO_TERMINATED);
+ if (code != CURLE_OK)
+ {
+ throw CURLException{code, "Could not build HTTP form."};
+ }
+ debuglog << "Set form part: " << name << " = " << arg << '\n';
+ }
+ }
+ }
+
+ return mime;
+}
+
} // namespace mastodonpp