Add support for parameters (GET).

This commit is contained in:
tastytea 2020-01-08 12:56:16 +01:00
parent 15c1e15466
commit c07fb1db71
Signed by: tastytea
GPG Key ID: CFC39497F1B26E07
5 changed files with 84 additions and 23 deletions

View File

@ -24,12 +24,16 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <variant>
namespace mastodonpp namespace mastodonpp
{ {
using std::string; using std::string;
using std::string_view; using std::string_view;
using std::variant;
using endpoint_variant = variant<API::endpoint_type,string>;
/*! /*!
* @brief Represents a connection to an instance. Used for requests. * @brief Represents a connection to an instance. Used for requests.
@ -51,25 +55,43 @@ public:
explicit Connection(Instance &instance); 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 * @since 0.1.0
*/ */
[[nodiscard]] [[nodiscard]]
answer_type get(const API::endpoint_type &endpoint); answer_type get(const endpoint_variant &endpoint,
const parametermap &parameters);
/*! /*!
* @brief Make a HTTP GET call. * @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 * @since 0.1.0
*/ */
[[nodiscard]] [[nodiscard]]
answer_type get(const string_view &endpoint); inline answer_type get(const endpoint_variant &endpoint)
{
return get(endpoint, {});
}
private: private:
Instance &_instance; Instance &_instance;

View File

@ -129,15 +129,17 @@ public:
protected: protected:
/*! /*!
* @brief Make a request. * @brief Make a HTTP request.
* *
* @param method The HTTP method. * @param method The HTTP method.
* @param uri The full URI. * @param uri The full URI.
* @param parameters A map of parameters.
* *
* @since 0.1.0 * @since 0.1.0
*/ */
[[nodiscard]] [[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 &parameters);
private: private:
CURL *_connection; CURL *_connection;

View File

@ -19,21 +19,27 @@
namespace mastodonpp namespace mastodonpp
{ {
using std::holds_alternative;
Connection::Connection(Instance &instance) Connection::Connection(Instance &instance)
: _instance{instance} : _instance{instance}
, _baseuri{instance.get_baseuri()} , _baseuri{instance.get_baseuri()}
{} {}
answer_type Connection::get(const API::endpoint_type &endpoint) answer_type Connection::get(const endpoint_variant &endpoint,
const parametermap &parameters)
{ {
return make_request( string uri{[&]
http_method::GET, {
string(_baseuri).append(API{endpoint}.to_string_view())); if (holds_alternative<API::endpoint_type>(endpoint))
} {
return string(_baseuri).append(
API{std::get<API::endpoint_type>(endpoint)}.to_string_view());
}
answer_type Connection::get(const string_view &endpoint) return std::get<string>(endpoint);
{ }()};
return make_request(http_method::GET, string(_baseuri).append(endpoint)); return make_request(http_method::GET, uri, parameters);
} }
} // namespace mastodonpp } // namespace mastodonpp

View File

@ -26,6 +26,8 @@
namespace mastodonpp namespace mastodonpp
{ {
using std::get;
using std::holds_alternative;
using std::atomic; using std::atomic;
using std::uint8_t; using std::uint8_t;
using std::uint16_t; using std::uint16_t;
@ -57,11 +59,9 @@ CURLWrapper::~CURLWrapper() noexcept
} }
} }
answer_type CURLWrapper::make_request(const http_method &method, answer_type CURLWrapper::make_request(const http_method &method, string uri,
const string_view &uri) const parametermap &parameters)
{ {
debuglog << "Making request to: " << uri << '\n';
CURLcode code; CURLcode code;
switch (method) switch (method)
{ {
@ -69,6 +69,36 @@ answer_type CURLWrapper::make_request(const http_method &method,
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
code = curl_easy_setopt(_connection, CURLOPT_HTTPGET, 1L); code = curl_easy_setopt(_connection, CURLOPT_HTTPGET, 1L);
for (const auto &param : parameters)
{
static bool first{true};
if (first)
{
uri.append("?");
first = false;
}
else
{
uri.append("&");
}
if (holds_alternative<string>(param.second))
{
uri.append(param.first + '=' + get<string>(param.second));
}
else
{
for (const auto &arg : get<vector<string>>(param.second))
{
uri.append(param.first + "[]=" + arg);
if (arg != *get<vector<string>>(param.second).rbegin())
{
uri.append("&");
}
}
}
}
break; break;
} }
case http_method::POST: 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", throw CURLException{code, "Failed to set HTTP method",
_curl_buffer_error}; _curl_buffer_error};
} }
debuglog << "Making request to: " << uri << '\n';
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
code = curl_easy_setopt(_connection, CURLOPT_URL, uri.data()); code = curl_easy_setopt(_connection, CURLOPT_URL, uri.data());

View File

@ -40,7 +40,7 @@ uint64_t Instance::get_max_chars()
{ {
debuglog << "Querying " << _hostname << " for max_toot_chars…\n"; debuglog << "Querying " << _hostname << " for max_toot_chars…\n";
const auto answer{make_request(http_method::GET, const auto answer{make_request(http_method::GET,
_baseuri + "/api/v1/instance")}; _baseuri + "/api/v1/instance", {})};
if (!answer) if (!answer)
{ {
debuglog << "Could not get instance info.\n"; debuglog << "Could not get instance info.\n";