LIBS: restclient-cpp lib (libcurl wrapper)
parent
307a43724d
commit
1fa365575a
|
@ -0,0 +1,2 @@
|
|||
include("${PROJECT_SOURCE_DIR}/cmake/macros.cmake")
|
||||
engine_find_header_only(restclient-cpp connection.h restclient-cpp "" "")
|
|
@ -140,8 +140,6 @@ macro(generate_protocol TARGET)
|
|||
set_source_files_properties(${GEN_DIR}/${HEADER} PROPERTIES GENERATED TRUE)
|
||||
endforeach()
|
||||
|
||||
message(STATUS "HEADERS: ${_headers}")
|
||||
|
||||
add_custom_target(GenerateNetworkMessages${TARGET}
|
||||
DEPENDS ${_headers}
|
||||
COMMENT "Generate network messages in ${GEN_DIR}"
|
||||
|
|
|
@ -9,3 +9,4 @@ add_subdirectory(sauce)
|
|||
add_subdirectory(turbobadger)
|
||||
add_subdirectory(gtest)
|
||||
add_subdirectory(sdl2)
|
||||
add_subdirectory(restclient-cpp)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
set(SRCS connection.cc helpers.cc restclient.cc)
|
||||
set(LIB restclient-cpp)
|
||||
engine_add_library(LIB ${LIB} SRCS ${SRCS})
|
||||
find_package(CURL REQUIRED)
|
||||
target_link_libraries(${LIB} ${CURL_LIBRARIES})
|
||||
target_include_directories(${LIB} PRIVATE ${CURL_INCLUDE_DIRS} .)
|
|
@ -0,0 +1,360 @@
|
|||
/**
|
||||
* @file connection.cpp
|
||||
* @brief implementation of the connection class
|
||||
* @author Daniel Schauenberg <d@unwiredcouch.com>
|
||||
*/
|
||||
|
||||
#include "restclient-cpp/connection.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "restclient-cpp/restclient.h"
|
||||
#include "restclient-cpp/helpers.h"
|
||||
#include "restclient-cpp/version.h"
|
||||
|
||||
/**
|
||||
* @brief constructor for the Connection object
|
||||
*
|
||||
* @param baseUrl - base URL for the connection to use
|
||||
*
|
||||
*/
|
||||
RestClient::Connection::Connection(const std::string baseUrl)
|
||||
: lastRequest(), headerFields() {
|
||||
this->curlHandle = curl_easy_init();
|
||||
if (!this->curlHandle) {
|
||||
throw std::runtime_error("Couldn't initialize curl handle");
|
||||
}
|
||||
this->baseUrl = baseUrl;
|
||||
this->timeout = 0;
|
||||
this->followRedirects = false;
|
||||
}
|
||||
|
||||
RestClient::Connection::~Connection() {
|
||||
if (this->curlHandle) {
|
||||
curl_easy_cleanup(this->curlHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// getters/setters
|
||||
|
||||
/**
|
||||
* @brief get diagnostic information about the connection object
|
||||
*
|
||||
* @return RestClient::Connection::Info struct
|
||||
*/
|
||||
RestClient::Connection::Info
|
||||
RestClient::Connection::GetInfo() {
|
||||
RestClient::Connection::Info ret;
|
||||
ret.baseUrl = this->baseUrl;
|
||||
ret.headers = this->GetHeaders();
|
||||
ret.timeout = this->timeout;
|
||||
ret.basicAuth.username = this->basicAuth.username;
|
||||
ret.basicAuth.password = this->basicAuth.password;
|
||||
ret.customUserAgent = this->customUserAgent;
|
||||
ret.lastRequest = this->lastRequest;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief append a header to the internal map
|
||||
*
|
||||
* @param key for the header field
|
||||
* @param value for the header field
|
||||
*
|
||||
*/
|
||||
void
|
||||
RestClient::Connection::AppendHeader(const std::string& key,
|
||||
const std::string& value) {
|
||||
this->headerFields[key] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set the custom headers map. This will replace the currently
|
||||
* configured headers with the provided ones. If you want to add additional
|
||||
* headers, use AppendHeader()
|
||||
*
|
||||
* @param headers to set
|
||||
*/
|
||||
void
|
||||
RestClient::Connection::SetHeaders(RestClient::HeaderFields headers) {
|
||||
this->headerFields = headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get all custom headers set on the connection
|
||||
*
|
||||
* @returns a RestClient::HeaderFields map containing the custom headers
|
||||
*/
|
||||
RestClient::HeaderFields
|
||||
RestClient::Connection::GetHeaders() {
|
||||
return this->headerFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure whether to follow redirects on this connection
|
||||
*
|
||||
* @param follow - boolean whether to follow redirects
|
||||
*/
|
||||
void
|
||||
RestClient::Connection::FollowRedirects(bool follow) {
|
||||
this->followRedirects = follow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set custom user agent for connection. This gets prepended to the
|
||||
* default restclient-cpp/RESTCLIENT_VERSION string
|
||||
*
|
||||
* @param userAgent - custom userAgent prefix
|
||||
*
|
||||
*/
|
||||
void
|
||||
RestClient::Connection::SetUserAgent(const std::string& userAgent) {
|
||||
this->customUserAgent = userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set custom Certificate Authority (CA) path
|
||||
*
|
||||
* @param caInfoFilePath - The path to a file holding the certificates used to
|
||||
* verify the peer with. See CURLOPT_CAINFO
|
||||
*
|
||||
*/
|
||||
void
|
||||
RestClient::Connection::SetCAInfoFilePath(const std::string& caInfoFilePath) {
|
||||
this->caInfoFilePath = caInfoFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the user agent to add to the request
|
||||
*
|
||||
* @return user agent as std::string
|
||||
*/
|
||||
std::string
|
||||
RestClient::Connection::GetUserAgent() {
|
||||
std::string prefix;
|
||||
if (this->customUserAgent.length() > 0) {
|
||||
prefix = this->customUserAgent + " ";
|
||||
}
|
||||
return std::string(prefix + "restclient-cpp/" + RESTCLIENT_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set timeout for connection
|
||||
*
|
||||
* @param seconds - timeout in seconds
|
||||
*
|
||||
*/
|
||||
void
|
||||
RestClient::Connection::SetTimeout(int seconds) {
|
||||
this->timeout = seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set username and password for basic auth
|
||||
*
|
||||
* @param username
|
||||
* @param password
|
||||
*
|
||||
*/
|
||||
void
|
||||
RestClient::Connection::SetBasicAuth(const std::string& username,
|
||||
const std::string& password) {
|
||||
this->basicAuth.username = username;
|
||||
this->basicAuth.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief helper function to get called from the actual request methods to
|
||||
* prepare the curlHandle for transfer with generic options, perform the
|
||||
* request and record some stats from the last request and then reset the
|
||||
* handle with curl_easy_reset to its default state. This will keep things
|
||||
* like connections and session ID intact but makes sure you can change
|
||||
* parameters on the object for another request.
|
||||
*
|
||||
* @param uri URI to query
|
||||
* @param ret Reference to the Response struct that should be filled
|
||||
*
|
||||
* @return 0 on success and 1 on error
|
||||
*/
|
||||
RestClient::Response
|
||||
RestClient::Connection::performCurlRequest(const std::string& uri) {
|
||||
// init return type
|
||||
RestClient::Response ret = {};
|
||||
|
||||
std::string url = std::string(this->baseUrl + uri);
|
||||
std::string headerString;
|
||||
CURLcode res = CURLE_OK;
|
||||
curl_slist* headerList = NULL;
|
||||
|
||||
/** set query URL */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_URL, url.c_str());
|
||||
/** set callback function */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_WRITEFUNCTION,
|
||||
Helpers::write_callback);
|
||||
/** set data object to pass to callback function */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_WRITEDATA, &ret);
|
||||
/** set the header callback function */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_HEADERFUNCTION,
|
||||
Helpers::header_callback);
|
||||
/** callback object for headers */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_HEADERDATA, &ret);
|
||||
/** set http headers */
|
||||
for (HeaderFields::const_iterator it = this->headerFields.begin();
|
||||
it != this->headerFields.end(); ++it) {
|
||||
headerString = it->first;
|
||||
headerString += ": ";
|
||||
headerString += it->second;
|
||||
headerList = curl_slist_append(headerList, headerString.c_str());
|
||||
}
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_HTTPHEADER,
|
||||
headerList);
|
||||
|
||||
// set basic auth if configured
|
||||
if (this->basicAuth.username.length() > 0) {
|
||||
std::string authString = std::string(this->basicAuth.username + ":" +
|
||||
this->basicAuth.password);
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_USERPWD, authString.c_str());
|
||||
}
|
||||
/** set user agent */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_USERAGENT,
|
||||
this->GetUserAgent().c_str());
|
||||
|
||||
// set timeout
|
||||
if (this->timeout) {
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_TIMEOUT, this->timeout);
|
||||
// dont want to get a sig alarm on timeout
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_NOSIGNAL, 1);
|
||||
}
|
||||
// set follow redirect
|
||||
if (this->followRedirects == true) {
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
}
|
||||
// if provided, supply CA path
|
||||
if (!this->caInfoFilePath.empty()) {
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_CAINFO,
|
||||
this->caInfoFilePath.c_str());
|
||||
}
|
||||
res = curl_easy_perform(this->curlHandle);
|
||||
if (res != CURLE_OK) {
|
||||
if (res == CURLE_OPERATION_TIMEDOUT) {
|
||||
ret.code = res;
|
||||
ret.body = "Operation Timeout.";
|
||||
} else {
|
||||
ret.body = "Failed to query.";
|
||||
ret.code = -1;
|
||||
}
|
||||
} else {
|
||||
int64_t http_code = 0;
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
ret.code = static_cast<int>(http_code);
|
||||
}
|
||||
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_TOTAL_TIME,
|
||||
&this->lastRequest.totalTime);
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_NAMELOOKUP_TIME,
|
||||
&this->lastRequest.nameLookupTime);
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_CONNECT_TIME,
|
||||
&this->lastRequest.connectTime);
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_APPCONNECT_TIME,
|
||||
&this->lastRequest.appConnectTime);
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_PRETRANSFER_TIME,
|
||||
&this->lastRequest.preTransferTime);
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_STARTTRANSFER_TIME,
|
||||
&this->lastRequest.startTransferTime);
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_REDIRECT_TIME,
|
||||
&this->lastRequest.redirectTime);
|
||||
curl_easy_getinfo(this->curlHandle, CURLINFO_REDIRECT_COUNT,
|
||||
&this->lastRequest.redirectCount);
|
||||
// free header list
|
||||
curl_slist_free_all(headerList);
|
||||
// reset curl handle
|
||||
curl_easy_reset(this->curlHandle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HTTP GET method
|
||||
*
|
||||
* @param url to query
|
||||
*
|
||||
* @return response struct
|
||||
*/
|
||||
RestClient::Response
|
||||
RestClient::Connection::get(const std::string& url) {
|
||||
return this->performCurlRequest(url);
|
||||
}
|
||||
/**
|
||||
* @brief HTTP POST method
|
||||
*
|
||||
* @param url to query
|
||||
* @param data HTTP POST body
|
||||
*
|
||||
* @return response struct
|
||||
*/
|
||||
RestClient::Response
|
||||
RestClient::Connection::post(const std::string& url,
|
||||
const std::string& data) {
|
||||
/** Now specify we want to POST data */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_POST, 1L);
|
||||
/** set post fields */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_POSTFIELDS, data.c_str());
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_POSTFIELDSIZE, data.size());
|
||||
|
||||
return this->performCurlRequest(url);
|
||||
}
|
||||
/**
|
||||
* @brief HTTP PUT method
|
||||
*
|
||||
* @param url to query
|
||||
* @param data HTTP PUT body
|
||||
*
|
||||
* @return response struct
|
||||
*/
|
||||
RestClient::Response
|
||||
RestClient::Connection::put(const std::string& url,
|
||||
const std::string& data) {
|
||||
/** initialize upload object */
|
||||
RestClient::Helpers::UploadObject up_obj;
|
||||
up_obj.data = data.c_str();
|
||||
up_obj.length = data.size();
|
||||
|
||||
/** Now specify we want to PUT data */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_PUT, 1L);
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_UPLOAD, 1L);
|
||||
/** set read callback function */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_READFUNCTION,
|
||||
RestClient::Helpers::read_callback);
|
||||
/** set data object to pass to callback function */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_READDATA, &up_obj);
|
||||
/** set data size */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_INFILESIZE,
|
||||
static_cast<int64_t>(up_obj.length));
|
||||
|
||||
return this->performCurlRequest(url);
|
||||
}
|
||||
/**
|
||||
* @brief HTTP DELETE method
|
||||
*
|
||||
* @param url to query
|
||||
*
|
||||
* @return response struct
|
||||
*/
|
||||
RestClient::Response
|
||||
RestClient::Connection::del(const std::string& url) {
|
||||
/** we want HTTP DELETE */
|
||||
const char* http_delete = "DELETE";
|
||||
|
||||
/** set HTTP DELETE METHOD */
|
||||
curl_easy_setopt(this->curlHandle, CURLOPT_CUSTOMREQUEST, http_delete);
|
||||
|
||||
return this->performCurlRequest(url);
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* @file helpers.cpp
|
||||
* @brief implementation of the restclient helpers
|
||||
* @author Daniel Schauenberg <d@unwiredcouch.com>
|
||||
*/
|
||||
|
||||
#include "restclient-cpp/helpers.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "restclient-cpp/restclient.h"
|
||||
|
||||
/**
|
||||
* @brief write callback function for libcurl
|
||||
*
|
||||
* @param data returned data of size (size*nmemb)
|
||||
* @param size size parameter
|
||||
* @param nmemb memblock parameter
|
||||
* @param userdata pointer to user data to save/work with return data
|
||||
*
|
||||
* @return (size * nmemb)
|
||||
*/
|
||||
size_t RestClient::Helpers::write_callback(void *data, size_t size,
|
||||
size_t nmemb, void *userdata) {
|
||||
RestClient::Response* r;
|
||||
r = reinterpret_cast<RestClient::Response*>(userdata);
|
||||
r->body.append(reinterpret_cast<char*>(data), size*nmemb);
|
||||
|
||||
return (size * nmemb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief header callback for libcurl
|
||||
*
|
||||
* @param data returned (header line)
|
||||
* @param size of data
|
||||
* @param nmemb memblock
|
||||
* @param userdata pointer to user data object to save headr data
|
||||
* @return size * nmemb;
|
||||
*/
|
||||
size_t RestClient::Helpers::header_callback(void *data, size_t size,
|
||||
size_t nmemb, void *userdata) {
|
||||
RestClient::Response* r;
|
||||
r = reinterpret_cast<RestClient::Response*>(userdata);
|
||||
std::string header(reinterpret_cast<char*>(data), size*nmemb);
|
||||
size_t seperator = header.find_first_of(":");
|
||||
if ( std::string::npos == seperator ) {
|
||||
// roll with non seperated headers...
|
||||
trim(header);
|
||||
if (0 == header.length()) {
|
||||
return (size * nmemb); // blank line;
|
||||
}
|
||||
r->headers[header] = "present";
|
||||
} else {
|
||||
std::string key = header.substr(0, seperator);
|
||||
trim(key);
|
||||
std::string value = header.substr(seperator + 1);
|
||||
trim(value);
|
||||
r->headers[key] = value;
|
||||
}
|
||||
|
||||
return (size * nmemb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief read callback function for libcurl
|
||||
*
|
||||
* @param data pointer of max size (size*nmemb) to write data to
|
||||
* @param size size parameter
|
||||
* @param nmemb memblock parameter
|
||||
* @param userdata pointer to user data to read data from
|
||||
*
|
||||
* @return (size * nmemb)
|
||||
*/
|
||||
size_t RestClient::Helpers::read_callback(void *data, size_t size,
|
||||
size_t nmemb, void *userdata) {
|
||||
/** get upload struct */
|
||||
RestClient::Helpers::UploadObject* u;
|
||||
u = reinterpret_cast<RestClient::Helpers::UploadObject*>(userdata);
|
||||
/** set correct sizes */
|
||||
size_t curl_size = size * nmemb;
|
||||
size_t copy_size = (u->length < curl_size) ? u->length : curl_size;
|
||||
/** copy data to buffer */
|
||||
std::memcpy(data, u->data, copy_size);
|
||||
/** decrement length and increment data pointer */
|
||||
u->length -= copy_size;
|
||||
u->data += copy_size;
|
||||
/** return copied size */
|
||||
return copy_size;
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/**
|
||||
* @file connection.h
|
||||
* @brief header definitions for restclient-cpp connection class
|
||||
* @author Daniel Schauenberg <d@unwiredcouch.com>
|
||||
* @version
|
||||
* @date 2010-10-11
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_RESTCLIENT_CPP_CONNECTION_H_
|
||||
#define INCLUDE_RESTCLIENT_CPP_CONNECTION_H_
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "restclient-cpp/restclient.h"
|
||||
#include "restclient-cpp/version.h"
|
||||
|
||||
/**
|
||||
* @brief namespace for all RestClient definitions
|
||||
*/
|
||||
namespace RestClient {
|
||||
|
||||
/**
|
||||
* @brief Connection object for advanced usage
|
||||
*/
|
||||
class Connection {
|
||||
public:
|
||||
/**
|
||||
* @struct RequestInfo
|
||||
* @brief holds some diagnostics information
|
||||
* about a request
|
||||
* @var RequestInfo::totalTime
|
||||
* Member 'totalTime' contains the total time of the last request in
|
||||
* seconds Total time of previous transfer. See CURLINFO_TOTAL_TIME
|
||||
* @var RequestInfo::nameLookupTime
|
||||
* Member 'nameLookupTime' contains the time spent in DNS lookup in
|
||||
* seconds Time from start until name resolving completed. See
|
||||
* CURLINFO_NAMELOOKUP_TIME
|
||||
* @var RequestInfo::connectTime
|
||||
* Member 'connectTime' contains the time it took until Time from start
|
||||
* until remote host or proxy completed. See CURLINFO_CONNECT_TIME
|
||||
* @var RequestInfo::appConnectTime
|
||||
* Member 'appConnectTime' contains the time from start until SSL/SSH
|
||||
* handshake completed. See CURLINFO_APPCONNECT_TIME
|
||||
* @var RequestInfo::preTransferTime
|
||||
* Member 'preTransferTime' contains the total time from start until
|
||||
* just before the transfer begins. See CURLINFO_PRETRANSFER_TIME
|
||||
* @var RequestInfo::startTransferTime
|
||||
* Member 'startTransferTime' contains the total time from start until
|
||||
* just when the first byte is received. See CURLINFO_STARTTRANSFER_TIME
|
||||
* @var RequestInfo::redirectTime
|
||||
* Member 'redirectTime' contains the total time taken for all redirect
|
||||
* steps before the final transfer. See CURLINFO_REDIRECT_TIME
|
||||
* @var RequestInfo::redirectCount
|
||||
* Member 'redirectCount' contains the number of redirects followed. See
|
||||
* CURLINFO_REDIRECT_COUNT
|
||||
*/
|
||||
typedef struct {
|
||||
double totalTime;
|
||||
double nameLookupTime;
|
||||
double connectTime;
|
||||
double appConnectTime;
|
||||
double preTransferTime;
|
||||
double startTransferTime;
|
||||
double redirectTime;
|
||||
int redirectCount;
|
||||
} RequestInfo;
|
||||
/**
|
||||
* @struct Info
|
||||
* @brief holds some diagnostics information
|
||||
* about the connection object it came from
|
||||
* @var Info::baseUrl
|
||||
* Member 'baseUrl' contains the base URL for the connection object
|
||||
* @var Info::headers
|
||||
* Member 'headers' contains the HeaderFields map
|
||||
* @var Info::timeout
|
||||
* Member 'timeout' contains the configured timeout
|
||||
* @var Info::followRedirects
|
||||
* Member 'followRedirects' contains whether or not to follow redirects
|
||||
* @var Info::basicAuth
|
||||
* Member 'basicAuth' contains information about basic auth
|
||||
* @var basicAuth::username
|
||||
* Member 'username' contains the basic auth username
|
||||
* @var basicAuth::password
|
||||
* Member 'password' contains the basic auth password
|
||||
* @var Info::customUserAgent
|
||||
* Member 'customUserAgent' contains the custom user agent
|
||||
* @var Info::lastRequest
|
||||
* Member 'lastRequest' contains metrics about the last request
|
||||
*/
|
||||
typedef struct {
|
||||
std::string baseUrl;
|
||||
RestClient::HeaderFields headers;
|
||||
int timeout;
|
||||
bool followRedirects;
|
||||
struct {
|
||||
std::string username;
|
||||
std::string password;
|
||||
} basicAuth;
|
||||
std::string customUserAgent;
|
||||
RequestInfo lastRequest;
|
||||
} Info;
|
||||
|
||||
|
||||
explicit Connection(const std::string baseUrl);
|
||||
~Connection();
|
||||
|
||||
// Instance configuration methods
|
||||
// configure basic auth
|
||||
void SetBasicAuth(const std::string& username,
|
||||
const std::string& password);
|
||||
|
||||
// set connection timeout to seconds
|
||||
void SetTimeout(int seconds);
|
||||
|
||||
// set whether to follow redirects
|
||||
void FollowRedirects(bool follow);
|
||||
|
||||
// set custom user agent
|
||||
// (this will result in the UA "foo/cool restclient-cpp/VERSION")
|
||||
void SetUserAgent(const std::string& userAgent);
|
||||
|
||||
// set the Certificate Authority (CA) Info which is the path to file holding
|
||||
// certificates to be used to verify peers. See CURLOPT_CAINFO
|
||||
void SetCAInfoFilePath(const std::string& caInfoFilePath);
|
||||
|
||||
std::string GetUserAgent();
|
||||
|
||||
RestClient::Connection::Info GetInfo();
|
||||
|
||||
// set headers
|
||||
void SetHeaders(RestClient::HeaderFields headers);
|
||||
|
||||
// get headers
|
||||
RestClient::HeaderFields GetHeaders();
|
||||
|
||||
// append additional headers
|
||||
void AppendHeader(const std::string& key,
|
||||
const std::string& value);
|
||||
|
||||
|
||||
// Basic HTTP verb methods
|
||||
RestClient::Response get(const std::string& uri);
|
||||
RestClient::Response post(const std::string& uri,
|
||||
const std::string& data);
|
||||
RestClient::Response put(const std::string& uri,
|
||||
const std::string& data);
|
||||
RestClient::Response del(const std::string& uri);
|
||||
|
||||
private:
|
||||
CURL* curlHandle;
|
||||
std::string baseUrl;
|
||||
RestClient::HeaderFields headerFields;
|
||||
int timeout;
|
||||
bool followRedirects;
|
||||
struct {
|
||||
std::string username;
|
||||
std::string password;
|
||||
} basicAuth;
|
||||
std::string customUserAgent;
|
||||
std::string caInfoFilePath;
|
||||
RequestInfo lastRequest;
|
||||
RestClient::Response performCurlRequest(const std::string& uri);
|
||||
};
|
||||
}; // namespace RestClient
|
||||
|
||||
#endif // INCLUDE_RESTCLIENT_CPP_CONNECTION_H_
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file helpers.h
|
||||
* @brief header file for restclient-cpp helpers
|
||||
* @author Daniel Schauenberg <d@unwiredcouch.com>
|
||||
* @version
|
||||
* @date 2010-10-11
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_RESTCLIENT_CPP_HELPERS_H_
|
||||
#define INCLUDE_RESTCLIENT_CPP_HELPERS_H_
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include "restclient-cpp/version.h"
|
||||
|
||||
/**
|
||||
* @brief namespace for all RestClient definitions
|
||||
*/
|
||||
namespace RestClient {
|
||||
|
||||
/**
|
||||
* @brief: namespace for all helper functions
|
||||
*/
|
||||
namespace Helpers {
|
||||
|
||||
/** @struct UploadObject
|
||||
* @brief This structure represents the payload to upload on POST
|
||||
* requests
|
||||
* @var UploadObject::data
|
||||
* Member 'data' contains the data to upload
|
||||
* @var UploadObject::length
|
||||
* Member 'length' contains the length of the data to upload
|
||||
*/
|
||||
typedef struct {
|
||||
const char* data;
|
||||
size_t length;
|
||||
} UploadObject;
|
||||
|
||||
// writedata callback function
|
||||
size_t write_callback(void *ptr, size_t size, size_t nmemb,
|
||||
void *userdata);
|
||||
|
||||
// header callback function
|
||||
size_t header_callback(void *ptr, size_t size, size_t nmemb,
|
||||
void *userdata);
|
||||
// read callback function
|
||||
size_t read_callback(void *ptr, size_t size, size_t nmemb,
|
||||
void *userdata);
|
||||
|
||||
// trim from start
|
||||
static inline std::string <rim(std::string &s) { // NOLINT
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from end
|
||||
static inline std::string &rtrim(std::string &s) { // NOLINT
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from both ends
|
||||
static inline std::string &trim(std::string &s) { // NOLINT
|
||||
return ltrim(rtrim(s));
|
||||
}
|
||||
}; // namespace Helpers
|
||||
|
||||
}; // namespace RestClient
|
||||
|
||||
#endif // INCLUDE_RESTCLIENT_CPP_HELPERS_H_
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file restclient.h
|
||||
* @brief libcurl wrapper for REST calls
|
||||
* @author Daniel Schauenberg <d@unwiredcouch.com>
|
||||
* @version
|
||||
* @date 2010-10-11
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_RESTCLIENT_CPP_RESTCLIENT_H_
|
||||
#define INCLUDE_RESTCLIENT_CPP_RESTCLIENT_H_
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "restclient-cpp/version.h"
|
||||
|
||||
/**
|
||||
* @brief namespace for all RestClient definitions
|
||||
*/
|
||||
namespace RestClient {
|
||||
|
||||
/**
|
||||
* public data definitions
|
||||
*/
|
||||
typedef std::map<std::string, std::string> HeaderFields;
|
||||
|
||||
/** @struct Response
|
||||
* @brief This structure represents the HTTP response data
|
||||
* @var Response::code
|
||||
* Member 'code' contains the HTTP response code
|
||||
* @var Response::body
|
||||
* Member 'body' contains the HTTP response body
|
||||
* @var Response::headers
|
||||
* Member 'headers' contains the HTTP response headers
|
||||
*/
|
||||
typedef struct {
|
||||
int code;
|
||||
std::string body;
|
||||
HeaderFields headers;
|
||||
} Response;
|
||||
|
||||
// init and disable functions
|
||||
int init();
|
||||
void disable();
|
||||
|
||||
/**
|
||||
* public methods for the simple API. These don't allow a lot of
|
||||
* configuration but are meant for simple HTTP calls.
|
||||
*
|
||||
*/
|
||||
Response get(const std::string& url);
|
||||
Response post(const std::string& url,
|
||||
const std::string& content_type,
|
||||
const std::string& data);
|
||||
Response put(const std::string& url,
|
||||
const std::string& content_type,
|
||||
const std::string& data);
|
||||
Response del(const std::string& url);
|
||||
|
||||
}; // namespace RestClient
|
||||
|
||||
#endif // INCLUDE_RESTCLIENT_CPP_RESTCLIENT_H_
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef INCLUDE_RESTCLIENT_CPP_VERSION_H_
|
||||
#define INCLUDE_RESTCLIENT_CPP_VERSION_H_
|
||||
#define RESTCLIENT_VERSION "0.4.4-2-gad96b12"
|
||||
#endif // INCLUDE_RESTCLIENT_CPP_VERSION_H_
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* @file restclient.cpp
|
||||
* @brief implementation of the restclient class
|
||||
*
|
||||
* This just provides static wrappers around the Connection class REST
|
||||
* methods. However since I didn't want to have to pull in a whole URI parsing
|
||||
* library just now, the Connection constructor is passed an empty string and
|
||||
* the full URL is passed to the REST methods. All those methods to is
|
||||
* concatenate them anyways. So this should do for now.
|
||||
*
|
||||
* @author Daniel Schauenberg <d@unwiredcouch.com>
|
||||
*/
|
||||
|
||||
#include "restclient-cpp/restclient.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "restclient-cpp/version.h"
|
||||
#include "restclient-cpp/connection.h"
|
||||
|
||||
/**
|
||||
* @brief global init function. Call this before you start any threads.
|
||||
*/
|
||||
int RestClient::init() {
|
||||
CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
|
||||
if (res == CURLE_OK) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief global disable function. Call this before you terminate your
|
||||
* program.
|
||||
*/
|
||||
void RestClient::disable() {
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HTTP GET method
|
||||
*
|
||||
* @param url to query
|
||||
*
|
||||
* @return response struct
|
||||
*/
|
||||
RestClient::Response RestClient::get(const std::string& url) {
|
||||
RestClient::Response ret;
|
||||
RestClient::Connection *conn = new RestClient::Connection("");
|
||||
ret = conn->get(url);
|
||||
delete conn;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HTTP POST method
|
||||
*
|
||||
* @param url to query
|
||||
* @param ctype content type as string
|
||||
* @param data HTTP POST body
|
||||
*
|
||||
* @return response struct
|
||||
*/
|
||||
RestClient::Response RestClient::post(const std::string& url,
|
||||
const std::string& ctype,
|
||||
const std::string& data) {
|
||||
RestClient::Response ret;
|
||||
RestClient::Connection *conn = new RestClient::Connection("");
|
||||
conn->AppendHeader("Content-Type", ctype);
|
||||
ret = conn->post(url, data);
|
||||
delete conn;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HTTP PUT method
|
||||
*
|
||||
* @param url to query
|
||||
* @param ctype content type as string
|
||||
* @param data HTTP PUT body
|
||||
*
|
||||
* @return response struct
|
||||
*/
|
||||
RestClient::Response RestClient::put(const std::string& url,
|
||||
const std::string& ctype,
|
||||
const std::string& data) {
|
||||
RestClient::Response ret;
|
||||
RestClient::Connection *conn = new RestClient::Connection("");
|
||||
conn->AppendHeader("Content-Type", ctype);
|
||||
ret = conn->put(url, data);
|
||||
delete conn;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HTTP DELETE method
|
||||
*
|
||||
* @param url to query
|
||||
*
|
||||
* @return response struct
|
||||
*/
|
||||
RestClient::Response RestClient::del(const std::string& url) {
|
||||
RestClient::Response ret;
|
||||
RestClient::Connection *conn = new RestClient::Connection("");
|
||||
ret = conn->del(url);
|
||||
delete conn;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -255,7 +255,7 @@ void Client::signup(const std::string& email, const std::string& password) {
|
|||
}
|
||||
|
||||
void Client::lostPassword(const std::string& email) {
|
||||
// TOOD:
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void Client::authFailed() {
|
||||
|
|
|
@ -9,6 +9,6 @@ set(SRCS
|
|||
set(LIB network)
|
||||
add_library(${LIB} ${SRCS})
|
||||
|
||||
target_link_libraries(${LIB} core enet flatbuffers)
|
||||
target_link_libraries(${LIB} core enet flatbuffers restclient-cpp)
|
||||
set_target_properties(${LIB} PROPERTIES FOLDER ${LIB})
|
||||
generate_protocol(${LIB} Shared.fbs ClientMessages.fbs ServerMessages.fbs)
|
||||
|
|
Loading…
Reference in New Issue