mastodonpp  0.2.0
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

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...
 
void set_proxy (string_view proxy)
 Set the proxy to use. 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...
 
void set_access_token (const string_view access_token)
 Set OAuth 2.0 Bearer Access Token. 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
42  : _curl_buffer_error{}
43  , _stream_cancelled(false)
44 {
45  if (curlwrapper_instances == 0)
46  {
47  curl_global_init(CURL_GLOBAL_ALL); // NOLINT(hicpp-signed-bitwise)
48  }
49  ++curlwrapper_instances;
50  debuglog << "CURLWrapper instances: " << curlwrapper_instances << " (+1)\n";
51 
52  _connection = curl_easy_init();
53  setup_curl();
54 }

◆ 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.

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

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

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
205  {
206  _stream_cancelled = true;
207  }

◆ get_buffer()

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

Returns a reference to the buffer libcurl writes into.

Since
0.1.0
191  {
192  return _curl_buffer_body;
193  }

◆ 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
144  {
145  return _connection;
146  }

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

◆ 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 ( const string_view  access_token)
protected

Set OAuth 2.0 Bearer Access Token.

Since
0.1.0
201 {
202  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise)
203  CURLcode code{curl_easy_setopt(_connection, CURLOPT_XOAUTH2_BEARER,
204  access_token.data())};
205  if (code != CURLE_OK)
206  {
207  throw CURLException{code, "Could not set authorization token.",
208  _curl_buffer_error};
209  }
210 
211 #if (LIBCURL_VERSION_NUM < 0x073d00) // libcurl < 7.61.0.
212 #define CURLAUTH_BEARER CURLAUTH_ANY
213 #endif
214 
215  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise)
216  code = curl_easy_setopt(_connection, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
217  if (code != CURLE_OK)
218  {
219  throw CURLException{code, "Could not set authorization token.",
220  _curl_buffer_error};
221  }
222 
223  debuglog << "Set authorization token.\n";
224 }

◆ set_proxy()

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

Set the proxy to use.

See CURLOPT_PROXY(3).

Parameters
proxyExamples: "socks4a://127.0.0.1:9050", "http://[::1]:3128".
Since
0.1.0
68 {
69  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
70  CURLcode code{curl_easy_setopt(_connection, CURLOPT_PROXY, proxy.data())};
71  if (code != CURLE_OK)
72  {
73  throw CURLException{code, "Failed to set proxy", _curl_buffer_error};
74  }
75 }

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: