Add HTTP GET function
The function performs a HTTP GET on a URL and returns the HTTP response.
This commit is contained in:
@ -16,7 +16,7 @@ then
|
|||||||
build-essential libssl-dev ncurses-dev bison flex \
|
build-essential libssl-dev ncurses-dev bison flex \
|
||||||
perl libtool libpcre3-dev tcl tcl-dev uuid \
|
perl libtool libpcre3-dev tcl tcl-dev uuid \
|
||||||
uuid-dev libsqlite3-dev liblzma-dev libpam0g-dev pkg-config \
|
uuid-dev libsqlite3-dev liblzma-dev libpam0g-dev pkg-config \
|
||||||
libedit-dev
|
libedit-dev libcurl4-openssl-dev
|
||||||
|
|
||||||
## separatelibgnutls installation process for Ubuntu Trusty
|
## separatelibgnutls installation process for Ubuntu Trusty
|
||||||
cat /etc/*release | grep -E "Trusty|wheezy"
|
cat /etc/*release | grep -E "Trusty|wheezy"
|
||||||
@ -49,7 +49,7 @@ else
|
|||||||
make libtool libopenssl-devel libaio libaio-devel flex \
|
make libtool libopenssl-devel libaio libaio-devel flex \
|
||||||
pcre-devel git wget tcl libuuid-devel \
|
pcre-devel git wget tcl libuuid-devel \
|
||||||
xz-devel sqlite3 sqlite3-devel pkg-config lua lua-devel \
|
xz-devel sqlite3 sqlite3-devel pkg-config lua lua-devel \
|
||||||
gnutls-devel libgcrypt-devel pam-devel
|
gnutls-devel libgcrypt-devel pam-devel libcurl-devel
|
||||||
sudo zypper -n install rpm-build
|
sudo zypper -n install rpm-build
|
||||||
cat /etc/*-release | grep "SUSE Linux Enterprise Server 11"
|
cat /etc/*-release | grep "SUSE Linux Enterprise Server 11"
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ else
|
|||||||
libedit-devel systemtap-sdt-devel rpm-sign wget \
|
libedit-devel systemtap-sdt-devel rpm-sign wget \
|
||||||
gnupg pcre-devel flex rpmdevtools git wget tcl openssl libuuid-devel xz-devel \
|
gnupg pcre-devel flex rpmdevtools git wget tcl openssl libuuid-devel xz-devel \
|
||||||
sqlite sqlite-devel pkgconfig lua lua-devel rpm-build createrepo yum-utils \
|
sqlite sqlite-devel pkgconfig lua lua-devel rpm-build createrepo yum-utils \
|
||||||
gnutls-devel libgcrypt-devel pam-devel
|
gnutls-devel libgcrypt-devel pam-devel libcurl-devel
|
||||||
|
|
||||||
# Attempt to install libasan, it'll only work on CentOS 7
|
# Attempt to install libasan, it'll only work on CentOS 7
|
||||||
sudo yum install -y --nogpgcheck libasan
|
sudo yum install -y --nogpgcheck libasan
|
||||||
|
|||||||
@ -44,6 +44,7 @@ find_package(GSSAPI)
|
|||||||
find_package(SQLite)
|
find_package(SQLite)
|
||||||
find_package(ASAN)
|
find_package(ASAN)
|
||||||
find_package(TSAN)
|
find_package(TSAN)
|
||||||
|
find_package(CURL)
|
||||||
|
|
||||||
# Build PCRE2 so we always know the version
|
# Build PCRE2 so we always know the version
|
||||||
# Read BuildPCRE2 for details about how to add pcre2 as a dependency to a target
|
# Read BuildPCRE2 for details about how to add pcre2 as a dependency to a target
|
||||||
|
|||||||
@ -11,6 +11,7 @@ requirements are as follows:
|
|||||||
* Flex 2.5.35 or later
|
* Flex 2.5.35 or later
|
||||||
* libuuid
|
* libuuid
|
||||||
* GNUTLS
|
* GNUTLS
|
||||||
|
* libcurl
|
||||||
|
|
||||||
This is the minimum set of requirements that must be met to build the MaxScale
|
This is the minimum set of requirements that must be met to build the MaxScale
|
||||||
core package.
|
core package.
|
||||||
|
|||||||
@ -22,12 +22,14 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <maxscale/buffer.h>
|
#include <maxscale/buffer.h>
|
||||||
#include <maxscale/utils.h>
|
#include <maxscale/utils.h>
|
||||||
|
#include <maxscale/jansson.hh>
|
||||||
|
|
||||||
namespace maxscale
|
namespace maxscale
|
||||||
{
|
{
|
||||||
@ -645,4 +647,26 @@ uint64_t get_byteN(const uint8_t* ptr, int bytes);
|
|||||||
*/
|
*/
|
||||||
uint8_t* set_byteN(uint8_t* ptr, uint64_t value, int bytes);
|
uint8_t* set_byteN(uint8_t* ptr, uint64_t value, int bytes);
|
||||||
|
|
||||||
|
namespace http
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Result
|
||||||
|
{
|
||||||
|
int code; // HTTP response code
|
||||||
|
std::string raw_body; // Raw response body
|
||||||
|
std::unique_ptr<json_t> body; // JSON form of the body if it was valid JSON
|
||||||
|
std::unordered_map<std::string, std::string> headers; // Headers attached to the response
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a HTTP GET
|
||||||
|
*
|
||||||
|
* @param url URL to use
|
||||||
|
*
|
||||||
|
* @return A Result
|
||||||
|
*/
|
||||||
|
Result get(const std::string& url);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,6 +74,7 @@ target_link_libraries(maxscale-common
|
|||||||
gnutls
|
gnutls
|
||||||
gcrypt
|
gcrypt
|
||||||
${MICROHTTPD_LIBRARIES}
|
${MICROHTTPD_LIBRARIES}
|
||||||
|
${CURL_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
find_library(HAVE_LIBDL NAMES dl)
|
find_library(HAVE_LIBDL NAMES dl)
|
||||||
|
|||||||
@ -40,6 +40,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include <maxscale/alloc.h>
|
#include <maxscale/alloc.h>
|
||||||
#include <maxscale/config.h>
|
#include <maxscale/config.h>
|
||||||
@ -1198,4 +1199,84 @@ std::string string_printf(const char* format, ...)
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||||
|
{
|
||||||
|
std::string* buf = static_cast<std::string*>(userdata);
|
||||||
|
|
||||||
|
if (nmemb > 0)
|
||||||
|
{
|
||||||
|
buf->append(ptr, nmemb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nmemb;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t header_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, std::string>* map =
|
||||||
|
static_cast<std::unordered_map<std::string, std::string>*>(userdata);
|
||||||
|
|
||||||
|
if (nmemb > 0)
|
||||||
|
{
|
||||||
|
std::string data(ptr, size * nmemb);
|
||||||
|
auto pos = data.find_first_of(':');
|
||||||
|
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string key = data.substr(0, pos);
|
||||||
|
std::string value = data.substr(pos + 1);
|
||||||
|
trim(key);
|
||||||
|
trim(value);
|
||||||
|
map->insert(std::make_pair(key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nmemb * size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace http
|
||||||
|
{
|
||||||
|
|
||||||
|
Result get(const std::string& url)
|
||||||
|
{
|
||||||
|
Result res;
|
||||||
|
char errbuf[CURL_ERROR_SIZE + 1] = "";
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &res.raw_body);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &res.headers);
|
||||||
|
|
||||||
|
long code = 0; // needs to be a long
|
||||||
|
|
||||||
|
if (curl_easy_perform(curl) == CURLE_OK)
|
||||||
|
{
|
||||||
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||||
|
res.code = code;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.code = -1;
|
||||||
|
res.raw_body = errbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even the errors are valid JSON so this should be OK
|
||||||
|
json_error_t err;
|
||||||
|
res.body.reset(json_loads(res.raw_body.c_str(), 0, &err));
|
||||||
|
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
return std::move(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user