/usr/include/leatherman/curl/client.hpp is in libleatherman-dev 1.4.0+dfsg-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | /**
* @file
* Declares the HTTP client.
*/
#pragma once
#include <leatherman/util/scoped_resource.hpp>
#include <leatherman/locale/locale.hpp>
#include "request.hpp"
#include "response.hpp"
#include <curl/curl.h>
#include <boost/optional.hpp>
#include <boost/filesystem.hpp>
#include <boost/nowide/cstdio.hpp>
#include "export.h"
namespace leatherman { namespace curl {
/**
* Resource for a cURL handle.
*/
struct LEATHERMAN_CURL_EXPORT curl_handle : util::scoped_resource<CURL*>
{
/**
* Constructs a cURL handle.
*/
curl_handle();
private:
static void cleanup(CURL* curl);
};
/**
* Resource for a cURL linked-list.
*/
struct LEATHERMAN_CURL_EXPORT curl_list : util::scoped_resource<curl_slist*>
{
/**
* Constructs a curl_list.
*/
curl_list();
/**
* Appends the given string onto the list.
* @param value The string to append onto the list.
*/
void append(std::string const& value);
private:
static void cleanup(curl_slist* list);
};
/**
* Resource for a cURL escaped string.
*/
struct LEATHERMAN_CURL_EXPORT curl_escaped_string : util::scoped_resource<char const*>
{
/**
* Constructs a cURL escaped string.
* @param handle The cURL handle to use to perform the escape.
* @param str The string to escape.
*/
curl_escaped_string(curl_handle const& handle, std::string const& str);
private:
static void cleanup(char const* str);
};
/**
* Resource for a temporary file used during download
*/
struct LEATHERMAN_CURL_NO_EXPORT download_temp_file
{
/**
* Constructs a temporary file that will be used to store the downloaded file's
* contents.
* @param req The HTTP request.
* @param file_path The file path that this temporary file's contents will be written to.
* @param perms The (optional) permissions of the downloaded file.
*/
download_temp_file(request const& req, std::string const& file_path, boost::optional<boost::filesystem::perms> perms);
~download_temp_file();
/*
* Returns the underlying file pointer.
*/
FILE* get_fp();
/*
* Writes the temporary file's contents to its file path.
*/
void write();
/*
* Writes the temporary file's contents to the body of the
* given response.
* @param response The HTTP response to write the contents to
*/
void write(response& res);
private:
void close_fp();
void cleanup();
FILE* _fp;
request _req;
std::string _file_path;
boost::filesystem::path _temp_path;
};
/**
* The exception for HTTP.
*/
struct LEATHERMAN_CURL_EXPORT http_exception : std::runtime_error
{
/**
* Constructs an http_exception.
* @param message The exception message.
*/
http_exception(std::string const& message) :
runtime_error(message)
{
}
};
/**
* The exception for HTTP requests.
*/
struct LEATHERMAN_CURL_EXPORT http_request_exception : http_exception
{
/**
* Constructs an http_request_exception.
* @param req The HTTP request that caused the exception.
* @param message The exception message.
*/
http_request_exception(request req, std::string const &message) :
http_exception(message),
_req(std::move(req))
{
}
/**
* Gets the request associated with the exception
* @return Returns the request associated with the exception.
*/
request const& req() const
{
return _req;
}
private:
request _req;
};
/**
* The exception for curl_easy_setopt errors.
*/
struct LEATHERMAN_CURL_EXPORT http_curl_setup_exception : http_request_exception
{
/**
* Constructs an http_curl_setup_exception.
* @param req The HTTP request that caused the exception.
* @param message The exception message.
* @param curl_opt The CURL option that failed.
*/
http_curl_setup_exception(request req, CURLoption curl_opt, std::string const &message) :
http_request_exception(req, message),
_curl_opt(std::move(curl_opt))
{
}
/**
* Gets the CURL option associated with the exception
* @return Returns the CURL option associated with the exception.
*/
CURLoption const& curl_opt() const
{
return _curl_opt;
}
private:
CURLoption _curl_opt;
};
/**
* The exception for HTTP file download server-side errors.
*/
struct LEATHERMAN_CURL_EXPORT http_file_download_exception : http_request_exception
{
/**
* Constructs an http_file_download_exception.
* @param request The request that caused the exception
* @param file_path The file that was meant to be downloaded
* @param message The exception message.
*/
http_file_download_exception(request req, std::string file_path, std::string const &message) :
http_request_exception(req, message),
_file_path(std::move(file_path))
{
}
/**
* Gets the file_path associated with the exception
* @return Returns the file_path associated with the exception.
*/
std::string const& file_path() const
{
return _file_path;
}
private:
std::string _file_path;
};
/**
* The exception for HTTP file download file operation errors.
*/
struct LEATHERMAN_CURL_EXPORT http_file_operation_exception : http_request_exception
{
/**
* Constructs an http_file_operation_exception.
* @param request The request that caused the exception
* @param file_path The file that was meant to be downloaded
* @param message The exception message.
*/
http_file_operation_exception(request req, std::string file_path, std::string const &message) : http_file_operation_exception(req, file_path, "", message)
{
}
/**
* Constructs an http_file_operation_exception.
* @param request The request that caused the exception
* @param file_path The file that was meant to be downloaded
* @param temp_path The path to the temporary file that wasn't successfully cleaned up.
* @param message The exception message.
*/
http_file_operation_exception(request req, std::string file_path, std::string temp_path, std::string const &message) :
http_request_exception(req, message),
_file_path(file_path),
_temp_path(std::move(temp_path))
{
}
/**
* Gets the file_path associated with the exception
* @return Returns the file_path associated with the exception.
*/
std::string const& file_path() const
{
return _file_path;
}
/**
* Gets the temp_path associated with the exception
* @return Returns the temp_path associated with the exception.
*/
std::string const& temp_path() const
{
return _temp_path;
}
private:
std::string _file_path;
std::string _temp_path;
};
/**
* Implements a client for HTTP.
* Note: this class is not thread-safe.
*/
struct LEATHERMAN_CURL_EXPORT client
{
/**
* Constructs an HTTP client.
*/
client();
/**
* Moves the given client into this client.
* @param other The client to move into this client.
*/
client(client&& other);
/**
* Moves the given client into this client.
* @param other The client to move into this client.
* @return Returns this client.
*/
client& operator=(client&& other);
/**
* Performs a GET with the given request.
* @param req The HTTP request to perform.
* @return Returns the HTTP response.
*/
response get(request const& req);
/**
* Performs a POST with the given request.
* @param req The HTTP request to perform.
* @return Returns the HTTP response.
*/
response post(request const& req);
/**
* Performs a PUT with the given request.
* @param req The HTTP request to perform.
* @return Returns the HTTP response.
*/
response put(request const& req);
/**
* Downloads the file from the specified url.
* Throws http_file_download_exception if anything goes wrong.
* @param req The HTTP request to perform.
* @param file_path The file that the downloaded contents will be written to.
* @param perms The file permissions to apply when writing to file_path.
* On Windows this only toggles read-only.
*/
void download_file(request const& req,
std::string const& file_path,
boost::optional<boost::filesystem::perms> perms = {});
/**
* Downloads the file from the specified url.
* Throws http_file_download_exception if anything goes wrong.
* @param req The HTTP request to perform.
* @param file_path The file that the downloaded contents will be written to.
* @param response The HTTP response. The body will only be included if the response status is >= 400.
* @param perms The file permissions to apply when writing to file_path.
* On Windows this only toggles read-only.
*/
void download_file(request const& req,
std::string const& file_path,
response& res,
boost::optional<boost::filesystem::perms> perms = {});
/**
* Sets the path to the CA certificate file.
* @param cert_file The path to the CA certificate file.
*/
void set_ca_cert(std::string const& cert_file);
/**
* Set client SSL certificate and key.
* @param client_cert The path to the client's certificate file.
* @param client_key The path to the client's key file.
*/
void set_client_cert(std::string const& client_cert, std::string const& client_key);
/**
* Set and limit what protocols curl will support
* @param client_protocols bitmask of CURLPROTO_*
* (see more: http://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html)
*/
void set_supported_protocols(long client_protocols);
private:
client(client const&) = delete;
client& operator=(client const&) = delete;
enum struct http_method
{
get,
put,
post
};
struct context
{
context(request const& req, response& res) :
req(req),
res(res),
read_offset(0)
{
}
request const& req;
response& res;
size_t read_offset;
curl_list request_headers;
std::string response_buffer;
};
std::string _ca_cert;
std::string _client_cert;
std::string _client_key;
long _client_protocols = CURLPROTO_ALL;
response perform(http_method method, request const& req);
void download_file_helper(request const& req,
std::string const& file_path,
boost::optional<response&> res = {},
boost::optional<boost::filesystem::perms> perms = {});
LEATHERMAN_CURL_NO_EXPORT void set_method(context& ctx, http_method method);
LEATHERMAN_CURL_NO_EXPORT void set_url(context& ctx);
LEATHERMAN_CURL_NO_EXPORT void set_headers(context& ctx);
LEATHERMAN_CURL_NO_EXPORT void set_cookies(context& ctx);
LEATHERMAN_CURL_NO_EXPORT void set_body(context& ctx, http_method method);
LEATHERMAN_CURL_NO_EXPORT void set_timeouts(context& ctx);
LEATHERMAN_CURL_NO_EXPORT void set_header_write_callbacks(context& ctx);
LEATHERMAN_CURL_NO_EXPORT void set_write_callbacks(context& ctx);
LEATHERMAN_CURL_NO_EXPORT void set_write_callbacks(context& ctx, FILE* fp);
LEATHERMAN_CURL_NO_EXPORT void set_client_info(context &ctx);
LEATHERMAN_CURL_NO_EXPORT void set_ca_info(context& ctx);
LEATHERMAN_CURL_NO_EXPORT void set_client_protocols(context& ctx);
template <typename ParamType>
LEATHERMAN_CURL_NO_EXPORT void curl_easy_setopt_maybe(
context &ctx,
CURLoption option,
ParamType const& param
) {
auto result = curl_easy_setopt(_handle, option, param);
if (result != CURLE_OK) {
throw http_curl_setup_exception(ctx.req, option, leatherman::locale::_("Failed setting up libcurl. Reason: {1}", curl_easy_strerror(result)));
}
}
static size_t read_body(char* buffer, size_t size, size_t count, void* ptr);
static int seek_body(void* ptr, curl_off_t offset, int origin);
static size_t write_header(char* buffer, size_t size, size_t count, void* ptr);
static size_t write_body(char* buffer, size_t size, size_t count, void* ptr);
static size_t write_file(char *buffer, size_t size, size_t count, void* ptr);
static int debug(CURL* handle, curl_infotype type, char* data, size_t size, void* ptr);
curl_handle _handle;
protected:
/**
* Returns a reference to a cURL handle resource used in the request.
* This is primarily exposed for testing.
* @return Returns a const reference to the cURL handle resource.
*/
curl_handle const& get_handle();
};
}} // namespace leatherman::curl
|