From c07fb1db71e8b4bc7f446f5f1945bfd1e09edd88 Mon Sep 17 00:00:00 2001 From: tastytea Date: Wed, 8 Jan 2020 12:56:16 +0100 Subject: [PATCH] Add support for parameters (GET). --- include/connection.hpp | 34 ++++++++++++++++++++++++++++------ include/curl_wrapper.hpp | 10 ++++++---- src/connection.cpp | 22 ++++++++++++++-------- src/curl_wrapper.cpp | 39 +++++++++++++++++++++++++++++++++++---- src/instance.cpp | 2 +- 5 files changed, 84 insertions(+), 23 deletions(-) diff --git a/include/connection.hpp b/include/connection.hpp index 6e43bc6..90027fb 100644 --- a/include/connection.hpp +++ b/include/connection.hpp @@ -24,12 +24,16 @@ #include #include +#include namespace mastodonpp { using std::string; using std::string_view; +using std::variant; + +using endpoint_variant = variant; /*! * @brief Represents a connection to an instance. Used for requests. @@ -51,25 +55,43 @@ public: explicit Connection(Instance &instance); /*! - * @brief Make a HTTP GET call. + * @brief Make a HTTP GET call with parameters. + * + * Example: + * @code + * auto answer{connection.get(mastodonpp::API::v1::accounts_id_followers, + * { + * {"id", "12"}, + * {"limit", "10"} + * })}; + * @endcode + * + * @param endpoint Endpoint as API::endpoint_type or `std::string`. + * @param parameters A map of parameters. * - * @param endpoint Endpoint as API::endpoint_type, for example: - * `mastodonpp::API::v1::instance`. * * @since 0.1.0 */ [[nodiscard]] - answer_type get(const API::endpoint_type &endpoint); + answer_type get(const endpoint_variant &endpoint, + const parametermap ¶meters); /*! * @brief Make a HTTP GET call. + * Example: + * @code + * auto answer{connection.get("/api/v1/instance")}; + * @endcode * - * @param endpoint Endpoint as string, for example: "/api/v1/instance". + * @param endpoint Endpoint as API::endpoint_type or `std::string`. * * @since 0.1.0 */ [[nodiscard]] - answer_type get(const string_view &endpoint); + inline answer_type get(const endpoint_variant &endpoint) + { + return get(endpoint, {}); + } private: Instance &_instance; diff --git a/include/curl_wrapper.hpp b/include/curl_wrapper.hpp index 01a753e..146e481 100644 --- a/include/curl_wrapper.hpp +++ b/include/curl_wrapper.hpp @@ -129,15 +129,17 @@ public: protected: /*! - * @brief Make a request. + * @brief Make a HTTP request. * - * @param method The HTTP method. - * @param uri The full URI. + * @param method The HTTP method. + * @param uri The full URI. + * @param parameters A map of parameters. * * @since 0.1.0 */ [[nodiscard]] - answer_type make_request(const http_method &method, const string_view &uri); + answer_type make_request(const http_method &method, string uri, + const parametermap ¶meters); private: CURL *_connection; diff --git a/src/connection.cpp b/src/connection.cpp index e6bca95..794247b 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -19,21 +19,27 @@ namespace mastodonpp { +using std::holds_alternative; + Connection::Connection(Instance &instance) : _instance{instance} , _baseuri{instance.get_baseuri()} {} -answer_type Connection::get(const API::endpoint_type &endpoint) +answer_type Connection::get(const endpoint_variant &endpoint, + const parametermap ¶meters) { - return make_request( - http_method::GET, - string(_baseuri).append(API{endpoint}.to_string_view())); -} + string uri{[&] + { + if (holds_alternative(endpoint)) + { + return string(_baseuri).append( + API{std::get(endpoint)}.to_string_view()); + } -answer_type Connection::get(const string_view &endpoint) -{ - return make_request(http_method::GET, string(_baseuri).append(endpoint)); + return std::get(endpoint); + }()}; + return make_request(http_method::GET, uri, parameters); } } // namespace mastodonpp diff --git a/src/curl_wrapper.cpp b/src/curl_wrapper.cpp index 76c9a2e..d153f7e 100644 --- a/src/curl_wrapper.cpp +++ b/src/curl_wrapper.cpp @@ -26,6 +26,8 @@ namespace mastodonpp { +using std::get; +using std::holds_alternative; using std::atomic; using std::uint8_t; using std::uint16_t; @@ -57,11 +59,9 @@ CURLWrapper::~CURLWrapper() noexcept } } -answer_type CURLWrapper::make_request(const http_method &method, - const string_view &uri) +answer_type CURLWrapper::make_request(const http_method &method, string uri, + const parametermap ¶meters) { - debuglog << "Making request to: " << uri << '\n'; - CURLcode code; switch (method) { @@ -69,6 +69,36 @@ answer_type CURLWrapper::make_request(const http_method &method, { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) code = curl_easy_setopt(_connection, CURLOPT_HTTPGET, 1L); + + for (const auto ¶m : parameters) + { + static bool first{true}; + if (first) + { + uri.append("?"); + first = false; + } + else + { + uri.append("&"); + } + if (holds_alternative(param.second)) + { + uri.append(param.first + '=' + get(param.second)); + } + else + { + for (const auto &arg : get>(param.second)) + { + uri.append(param.first + "[]=" + arg); + if (arg != *get>(param.second).rbegin()) + { + uri.append("&"); + } + } + } + } + break; } case http_method::POST: @@ -101,6 +131,7 @@ answer_type CURLWrapper::make_request(const http_method &method, throw CURLException{code, "Failed to set HTTP method", _curl_buffer_error}; } + debuglog << "Making request to: " << uri << '\n'; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) code = curl_easy_setopt(_connection, CURLOPT_URL, uri.data()); diff --git a/src/instance.cpp b/src/instance.cpp index 683e20e..e10675f 100644 --- a/src/instance.cpp +++ b/src/instance.cpp @@ -40,7 +40,7 @@ uint64_t Instance::get_max_chars() { debuglog << "Querying " << _hostname << " for max_toot_chars…\n"; const auto answer{make_request(http_method::GET, - _baseuri + "/api/v1/instance")}; + _baseuri + "/api/v1/instance", {})}; if (!answer) { debuglog << "Could not get instance info.\n";