mastodonpp  0.5.1
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
mastodonpp::CURLWrapper Class Reference

Handles the details of network connections. More...

#include <mastodonpp/curl_wrapper.hpp>

Inheritance diagram for mastodonpp::CURLWrapper:
mastodonpp::Connection mastodonpp::Instance mastodonpp::Instance::ObtainToken

Public Member Functions

 CURLWrapper ()
 Initializes curl and sets up connection. More...
 
 CURLWrapper (const CURLWrapper &other)=delete
 Copy constructor. More...
 
 CURLWrapper (CURLWrapper &&other) noexcept=delete
 Move constructor. More...
 
virtual ~CURLWrapper () noexcept
 Cleans up curl and connection. More...
 
CURLWrapperoperator= (const CURLWrapper &other)=delete
 Copy assignment operator. More...
 
CURLWrapperoperator= (CURLWrapper &&other) noexcept=delete
 Move assignment operator. More...
 
CURL * get_curl_easy_handle ()
 Returns pointer to the CURL easy handle. More...
 
string escape_url (const string_view url) const
 URL encodes the given string. More...
 
string unescape_url (const string_view url) const
 URL decodes the given string. More...
 
void setup_connection_properties (string_view proxy, string_view access_token, string_view cainfo, string_view useragent)
 Set some properties of the connection. More...
 

Protected Member Functions

answer_type make_request (const http_method &method, string uri, const parametermap &parameters)
 Make a HTTP request. More...
 
string & get_buffer ()
 Returns a reference to the buffer libcurl writes into. More...
 
void cancel_stream ()
 Cancel the stream. More...
 
virtual void set_proxy (string_view proxy)
 Set the proxy to use. More...
 
void set_access_token (string_view access_token)
 Set OAuth 2.0 Bearer Access Token. More...
 
virtual void set_cainfo (string_view path)
 Set path to Certificate Authority (CA) bundle. More...
 
virtual void set_useragent (string_view useragent)
 Sets the User-Agent. More...
 

Protected Attributes

mutex _buffer_mutex
 Mutex for get_buffer a.k.a. _curl_buffer_body. More...
 

Detailed Description

Handles the details of network connections.

You don't need to use this.

Since
0.1.0

Constructor & Destructor Documentation

◆ CURLWrapper() [1/3]

mastodonpp::CURLWrapper::CURLWrapper ( )

Initializes curl and sets up connection.

The first time an instance of CURLWrapper is created, it calls curl_global_init, which is not thread-safe. For more information consult curl_global_init(3).

Since
0.1.0
45  : _curl_buffer_error{}
46  , _stream_cancelled{false}
47 {
48  if (curlwrapper_instances == 0)
49  {
50  curl_global_init(CURL_GLOBAL_ALL); // NOLINT(hicpp-signed-bitwise)
51  }
52  ++curlwrapper_instances;
53  debuglog << "CURLWrapper instances: " << curlwrapper_instances << " (+1)\n";
54 
55  _connection = curl_easy_init();
56  setup_curl();
57 }

◆ CURLWrapper() [2/3]

mastodonpp::CURLWrapper::CURLWrapper ( const CURLWrapper other)
delete

Copy constructor.

◆ CURLWrapper() [3/3]

mastodonpp::CURLWrapper::CURLWrapper ( CURLWrapper &&  other)
deletenoexcept

Move constructor.

◆ ~CURLWrapper()

mastodonpp::CURLWrapper::~CURLWrapper ( )
virtualnoexcept

Cleans up curl and connection.

May call curl_global_cleanup, which is not thread-safe. For more information consult curl_global_cleanup(3).

Since
0.1.0
59 {
60  curl_easy_cleanup(_connection);
61 
62  --curlwrapper_instances;
63  debuglog << "CURLWrapper instances: " << curlwrapper_instances << " (-1)\n";
64  if (curlwrapper_instances == 0)
65  {
66  curl_global_cleanup();
67  }
68 }

Member Function Documentation

◆ cancel_stream()

void mastodonpp::CURLWrapper::cancel_stream ( )
inlineprotected

Cancel the stream.

The stream will be cancelled, usually whithin a second. The curl_error_code of the answer will be set to 42 (CURLE_ABORTED_BY_CALLBACK).

Since
0.1.0
211  {
212  _stream_cancelled = true;
213  }

◆ escape_url()

string mastodonpp::CURLWrapper::escape_url ( const string_view  url) const
inline

URL encodes the given string.

For more information consult curl_easy_escape(3).

Parameters
urlString to escape.
Returns
The escaped string or {} if it failed.
Since
0.3.0
124  {
125  char *cbuf{curl_easy_escape(_connection, url.data(),
126  static_cast<int>(url.size()))};
127  const string sbuf{cbuf};
128  curl_free(cbuf);
129  return sbuf;
130  }

◆ get_buffer()

string& mastodonpp::CURLWrapper::get_buffer ( )
inlineprotected

Returns a reference to the buffer libcurl writes into.

Since
0.1.0
197  {
198  return _curl_buffer_body;
199  }

◆ get_curl_easy_handle()

CURL* mastodonpp::CURLWrapper::get_curl_easy_handle ( )
inline

Returns pointer to the CURL easy handle.

You can use this handle to set or modify curl options. For more information consult curl_easy_setopt(3).

Since
0.1.0
106  {
107  return _connection;
108  }

◆ make_request()

answer_type mastodonpp::CURLWrapper::make_request ( const http_method method,
string  uri,
const parametermap parameters 
)
protected

Make a HTTP request.

Parameters
methodThe HTTP method.
uriThe full URI.
parametersA map of parameters.
Since
0.1.0
72 {
73  _stream_cancelled = false;
74  _curl_buffer_headers.clear();
75  _curl_buffer_body.clear();
76 
77  CURLcode code;
78  switch (method)
79  {
80  case http_method::GET:
81  {
82  add_parameters_to_uri(uri, parameters);
83  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
84  curl_easy_setopt(_connection, CURLOPT_HTTPGET, 1L);
85 
86  break;
87  }
88  case http_method::POST:
89  {
90  if (parameters.empty())
91  {
92  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
93  curl_easy_setopt(_connection, CURLOPT_POST, 1L);
94  }
95  else
96  {
97  curl_mime *mime{parameters_to_curl_mime(uri, parameters)};
98  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
99  curl_easy_setopt(_connection, CURLOPT_MIMEPOST, mime);
100  }
101 
102  break;
103  }
104  case http_method::PATCH:
105  {
106  if (!parameters.empty())
107  {
108  curl_mime *mime{parameters_to_curl_mime(uri, parameters)};
109  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
110  curl_easy_setopt(_connection, CURLOPT_MIMEPOST, mime);
111  }
112 
113  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
114  code = curl_easy_setopt(_connection, CURLOPT_CUSTOMREQUEST, "PATCH");
115  if (code != CURLE_OK)
116  {
117  throw CURLException{code, "Failed to set URI", _curl_buffer_error};
118  }
119 
120  break;
121  }
122  case http_method::PUT:
123  {
124  if (!parameters.empty())
125  {
126  curl_mime *mime{parameters_to_curl_mime(uri, parameters)};
127  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
128  curl_easy_setopt(_connection, CURLOPT_MIMEPOST, mime);
129  }
130 
131  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
132  code = curl_easy_setopt(_connection, CURLOPT_CUSTOMREQUEST, "PUT");
133  if (code != CURLE_OK)
134  {
135  throw CURLException{code, "Failed to set URI", _curl_buffer_error};
136  }
137 
138  break;
139  }
140  case http_method::DELETE:
141  {
142  if (!parameters.empty())
143  {
144  curl_mime *mime{parameters_to_curl_mime(uri, parameters)};
145  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
146  curl_easy_setopt(_connection, CURLOPT_MIMEPOST, mime);
147  }
148 
149  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
150  code = curl_easy_setopt(_connection, CURLOPT_CUSTOMREQUEST, "DELETE");
151  if (code != CURLE_OK)
152  {
153  throw CURLException{code, "Failed to set URI", _curl_buffer_error};
154  }
155 
156  break;
157  }
158  }
159  debuglog << "Making request to: " << uri << '\n';
160 
161  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
162  code = curl_easy_setopt(_connection, CURLOPT_URL, uri.data());
163  if (code != CURLE_OK)
164  {
165  throw CURLException{code, "Failed to set URI", _curl_buffer_error};
166  }
167 
168  answer_type answer;
169  code = curl_easy_perform(_connection);
170  if (code == CURLE_OK
171  || (code == CURLE_ABORTED_BY_CALLBACK && _stream_cancelled))
172  {
173  long http_status; // NOLINT(google-runtime-int)
174  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
175  curl_easy_getinfo(_connection, CURLINFO_RESPONSE_CODE, &http_status);
176  answer.http_status = static_cast<uint16_t>(http_status);
177  debuglog << "HTTP status code: " << http_status << '\n';
178 
179  answer.headers = _curl_buffer_headers;
180  answer.body = _curl_buffer_body;
181  }
182  else
183  {
184  answer.curl_error_code = static_cast<uint8_t>(code);
185  answer.error_message = _curl_buffer_error;
186  debuglog << "libcurl error: " << code << '\n';
187  debuglog << _curl_buffer_error << '\n';
188  }
189 
190  return answer;
191 }

◆ operator=() [1/2]

CURLWrapper& mastodonpp::CURLWrapper::operator= ( const CURLWrapper other)
delete

Copy assignment operator.

◆ operator=() [2/2]

CURLWrapper& mastodonpp::CURLWrapper::operator= ( CURLWrapper &&  other)
deletenoexcept

Move assignment operator.

◆ set_access_token()

void mastodonpp::CURLWrapper::set_access_token ( string_view  access_token)
protected

Set OAuth 2.0 Bearer Access Token.

Since
0.1.0
231 {
232  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise)
233  CURLcode code{curl_easy_setopt(_connection, CURLOPT_XOAUTH2_BEARER,
234  access_token.data())};
235  if (code != CURLE_OK)
236  {
237  throw CURLException{code, "Could not set authorization token.",
238  _curl_buffer_error};
239  }
240 
241 #if (LIBCURL_VERSION_NUM < 0x073d00) // libcurl < 7.61.0.
242 #define CURLAUTH_BEARER CURLAUTH_ANY
243 #endif
244 
245  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise)
246  code = curl_easy_setopt(_connection, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
247  if (code != CURLE_OK)
248  {
249  throw CURLException{code, "Could not set authorization token.",
250  _curl_buffer_error};
251  }
252 
253  debuglog << "Set authorization token.\n";
254 }

◆ set_cainfo()

void mastodonpp::CURLWrapper::set_cainfo ( string_view  path)
protectedvirtual

Set path to Certificate Authority (CA) bundle.

Since
0.3.0

Reimplemented in mastodonpp::Instance.

257 {
258  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
259  CURLcode code{curl_easy_setopt(_connection, CURLOPT_CAINFO, path.data())};
260  if (code != CURLE_OK)
261  {
262  throw CURLException{code, "Could not set CA info.", _curl_buffer_error};
263  }
264 }

◆ set_proxy()

void mastodonpp::CURLWrapper::set_proxy ( string_view  proxy)
protectedvirtual

Set the proxy to use.

See CURLOPT_PROXY(3).

Parameters
proxyExamples: "socks4a://127.0.0.1:9050", "http://[::1]:3128".
Since
0.1.0

Reimplemented in mastodonpp::Instance.

220 {
221  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
222  CURLcode code{curl_easy_setopt(_connection, CURLOPT_PROXY, proxy.data())};
223  if (code != CURLE_OK)
224  {
225  throw CURLException{code, "Failed to set proxy", _curl_buffer_error};
226  }
227  debuglog << "Set proxy to: " << proxy << '\n';
228 }

◆ set_useragent()

void mastodonpp::CURLWrapper::set_useragent ( string_view  useragent)
protectedvirtual

Sets the User-Agent.

Since
0.3.0

Reimplemented in mastodonpp::Instance.

267 {
268  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
269  CURLcode code{curl_easy_setopt(_connection, CURLOPT_USERAGENT,
270  useragent.data())};
271  if (code != CURLE_OK)
272  {
273  throw CURLException{code, "Failed to set User-Agent",
274  _curl_buffer_error};
275  }
276  debuglog << "Set User-Agent to: " << useragent << '\n';
277 }

◆ setup_connection_properties()

void mastodonpp::CURLWrapper::setup_connection_properties ( string_view  proxy,
string_view  access_token,
string_view  cainfo,
string_view  useragent 
)

Set some properties of the connection.

Meant for internal use. See Instance::copy_connection_properties().

Since
0.3.0
197 {
198  if (!proxy.empty())
199  {
200  set_proxy(proxy);
201  }
202 
203  if (!access_token.empty())
204  {
205  set_access_token(access_token);
206  }
207 
208  if (!cainfo.empty())
209  {
210  set_cainfo(cainfo);
211  }
212 
213  if (!useragent.empty())
214  {
215  set_useragent(useragent);
216  }
217 }

◆ unescape_url()

string mastodonpp::CURLWrapper::unescape_url ( const string_view  url) const
inline

URL decodes the given string.

For more information consult curl_easy_unescape(3).

Parameters
urlString to unescape.
Returns
The unescaped string or {} if it failed.
Since
0.3.0
146  {
147  char *cbuf{curl_easy_unescape(_connection, url.data(),
148  static_cast<int>(url.size()), nullptr)};
149  const string sbuf{cbuf};
150  curl_free(cbuf);
151  return sbuf;
152  }

Member Data Documentation

◆ _buffer_mutex

mutex mastodonpp::CURLWrapper::_buffer_mutex
protected

Mutex for get_buffer a.k.a. _curl_buffer_body.

This mutex is locked before anything is read or written from/to _curl_buffer_body.

Since
0.1.0

The documentation for this class was generated from the following files:
mastodonpp::CURLWrapper::set_proxy
virtual void set_proxy(string_view proxy)
Set the proxy to use.
Definition: curl_wrapper.cpp:219
mastodonpp::CURLWrapper::set_cainfo
virtual void set_cainfo(string_view path)
Set path to Certificate Authority (CA) bundle.
Definition: curl_wrapper.cpp:256
mastodonpp::CURLWrapper::set_useragent
virtual void set_useragent(string_view useragent)
Sets the User-Agent.
Definition: curl_wrapper.cpp:266
mastodonpp::CURLWrapper::set_access_token
void set_access_token(string_view access_token)
Set OAuth 2.0 Bearer Access Token.
Definition: curl_wrapper.cpp:230