mirror of
https://github.com/yhirose/cpp-httplib
synced 2026-06-08 18:30:49 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9af1a4a08f | |||
| 0654e5dab4 | |||
| 62e036f253 | |||
| f0adfb2e0c | |||
| 139c816c16 | |||
| 9505a76491 |
+160
@@ -0,0 +1,160 @@
|
||||
#[[
|
||||
Build options:
|
||||
* HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on)
|
||||
* HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on)
|
||||
* HTTPLIB_REQUIRE_OPENSSL (default off)
|
||||
* HTTPLIB_REQUIRE_ZLIB (default off)
|
||||
|
||||
After installation with Cmake, a find_package(httplib) is available.
|
||||
This creates a httplib::httplib target (if found).
|
||||
It can be linked like so:
|
||||
|
||||
target_link_libraries(your_exe httplib::httplib)
|
||||
|
||||
The following will build & install for later use.
|
||||
|
||||
Linux/macOS:
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
sudo cmake --build . --target install
|
||||
|
||||
Windows:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
runas /user:Administrator "cmake --build . --config Release --target install"
|
||||
|
||||
These three variables are available after you run find_package(httplib)
|
||||
* HTTPLIB_HEADER_PATH - this is the full path to the installed header.
|
||||
* HTTPLIB_IS_USING_OPENSSL - a bool for if OpenSSL support is enabled.
|
||||
* HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled.
|
||||
|
||||
Want to use precompiled headers (Cmake feature since v3.16)?
|
||||
It's as simple as doing the following (before linking):
|
||||
|
||||
target_precompile_headers(httplib::httplib INTERFACE "${HTTPLIB_HEADER_PATH}")
|
||||
]]
|
||||
cmake_minimum_required(VERSION 3.7.0 FATAL_ERROR)
|
||||
project(httplib LANGUAGES CXX)
|
||||
|
||||
# Change as needed to set an OpenSSL minimum version.
|
||||
# This is used in the installed Cmake config file.
|
||||
set(_HTTPLIB_OPENSSL_MIN_VER "1.1.1")
|
||||
|
||||
# Allow for a build to require OpenSSL to pass, instead of just being optional
|
||||
option(HTTPLIB_REQUIRE_OPENSSL "Requires OpenSSL to be found & linked, or fails build." OFF)
|
||||
option(HTTPLIB_REQUIRE_ZLIB "Requires ZLIB to be found & linked, or fails build." OFF)
|
||||
# Allow for a build to casually enable OpenSSL/ZLIB support, but silenty continue if not found.
|
||||
# Make these options so their automatic use can be specifically disabled (as needed)
|
||||
option(HTTPLIB_USE_OPENSSL_IF_AVAILABLE "Uses OpenSSL (if available) to enable HTTPS support." ON)
|
||||
option(HTTPLIB_USE_ZLIB_IF_AVAILABLE "Uses ZLIB (if available) to enable compression support." ON)
|
||||
|
||||
# TODO: implement the option of option to correctly split, building, and export with the split.py script.
|
||||
# option(HTTPLIB_SPLIT "Uses a Python script to split the header into a header & source file." OFF)
|
||||
|
||||
# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
|
||||
find_package(Threads REQUIRED)
|
||||
if(HTTPLIB_REQUIRE_OPENSSL)
|
||||
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} REQUIRED)
|
||||
elseif(HTTPLIB_USE_OPENSSL_IF_AVAILABLE)
|
||||
# Look quietly since it's optional are optional
|
||||
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} QUIET)
|
||||
endif()
|
||||
if(HTTPLIB_REQUIRE_ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
elseif(HTTPLIB_USE_ZLIB_IF_AVAILABLE)
|
||||
find_package(ZLIB QUIET)
|
||||
endif()
|
||||
|
||||
# Used for default, common dirs that the end-user can change (if needed)
|
||||
# like CMAKE_INSTALL_INCLUDEDIR or CMAKE_INSTALL_DATADIR
|
||||
include(GNUInstallDirs)
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
# Lets you address the target with httplib::httplib
|
||||
# Only useful if building in-tree, versus using it from an installation.
|
||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||
|
||||
# Might be missing some, but this list is somewhat comprehensive
|
||||
target_compile_features(${PROJECT_NAME} INTERFACE
|
||||
cxx_std_11
|
||||
cxx_nullptr
|
||||
cxx_noexcept
|
||||
cxx_lambdas
|
||||
cxx_override
|
||||
cxx_defaulted_functions
|
||||
cxx_attribute_deprecated
|
||||
cxx_auto_type
|
||||
cxx_decltype
|
||||
cxx_deleted_functions
|
||||
cxx_range_for
|
||||
cxx_sizeof_member
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE
|
||||
# Always require threads
|
||||
Threads::Threads
|
||||
# Only link zlib & openssl if they're found
|
||||
$<$<BOOL:${ZLIB_FOUND}>:ZLIB::ZLIB>
|
||||
$<$<BOOL:${OPENSSL_FOUND}>:OpenSSL::SSL OpenSSL::Crypto>
|
||||
)
|
||||
|
||||
# Auto-define the optional support if those packages were found
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE
|
||||
$<$<BOOL:${ZLIB_FOUND}>:CPPHTTPLIB_ZLIB_SUPPORT>
|
||||
$<$<BOOL:${OPENSSL_FOUND}>:CPPHTTPLIB_OPENSSL_SUPPORT>
|
||||
)
|
||||
|
||||
# Cmake's find_package search path is different based on the system
|
||||
# See https://cmake.org/cmake/help/latest/command/find_package.html for the list
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(_TARGET_INSTALL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/cmake/${PROJECT_NAME}")
|
||||
else()
|
||||
# On Non-Windows, it should be /usr/lib/cmake/<name>/<name>Config.cmake
|
||||
# NOTE: This may or may not work for macOS...
|
||||
set(_TARGET_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
# Configures the meta-file httplibConfig.cmake.in to replace variables with paths/values/etc.
|
||||
configure_package_config_file("${PROJECT_NAME}Config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION "${_TARGET_INSTALL_CMAKEDIR}"
|
||||
# Passes the includedir install path
|
||||
PATH_VARS CMAKE_INSTALL_FULL_INCLUDEDIR
|
||||
# There aren't any components, so don't use the macro
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
)
|
||||
|
||||
# Creates the export httplibTargets.cmake
|
||||
# This is strictly what holds compilation requirements
|
||||
# and linkage information (doesn't find deps though).
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT httplibTargets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
install(FILES httplib.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
|
||||
)
|
||||
|
||||
# NOTE: This path changes depending on if it's on Windows or Linux
|
||||
install(EXPORT httplibTargets
|
||||
# Puts the targets into the httplib namespace
|
||||
# So this makes httplib::httplib linkable after doing find_package(httplib)
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
|
||||
)
|
||||
@@ -40,6 +40,18 @@
|
||||
#define CPPHTTPLIB_WRITE_TIMEOUT_USECOND 0
|
||||
#endif
|
||||
|
||||
#ifndef CPPHTTPLIB_IDLE_INTERVAL_SECOND
|
||||
#define CPPHTTPLIB_IDLE_INTERVAL_SECOND 0
|
||||
#endif
|
||||
|
||||
#ifndef CPPHTTPLIB_IDLE_INTERVAL_USECOND
|
||||
#ifdef _WIN32
|
||||
#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 10000
|
||||
#else
|
||||
#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CPPHTTPLIB_REQUEST_URI_MAX_LENGTH
|
||||
#define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192
|
||||
#endif
|
||||
@@ -518,6 +530,7 @@ public:
|
||||
void set_keep_alive_max_count(size_t count);
|
||||
void set_read_timeout(time_t sec, time_t usec);
|
||||
void set_write_timeout(time_t sec, time_t usec);
|
||||
void set_idle_interval(time_t sec, time_t usec);
|
||||
void set_payload_max_length(size_t length);
|
||||
|
||||
bool bind_to_port(const char *host, int port, int socket_flags = 0);
|
||||
@@ -536,12 +549,14 @@ protected:
|
||||
bool &connection_close,
|
||||
const std::function<void(Request &)> &setup_request);
|
||||
|
||||
size_t keep_alive_max_count_;
|
||||
time_t read_timeout_sec_;
|
||||
time_t read_timeout_usec_;
|
||||
time_t write_timeout_sec_;
|
||||
time_t write_timeout_usec_;
|
||||
size_t payload_max_length_;
|
||||
size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
|
||||
time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
|
||||
time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
|
||||
time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
|
||||
time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
|
||||
time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND;
|
||||
time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND;
|
||||
size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH;
|
||||
|
||||
private:
|
||||
using Handlers = std::vector<std::pair<std::regex, Handler>>;
|
||||
@@ -988,6 +1003,339 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
class Client2 {
|
||||
public:
|
||||
explicit Client2(const char *scheme_host_port)
|
||||
: Client2(scheme_host_port, std::string(), std::string()) {}
|
||||
|
||||
explicit Client2(const char *scheme_host_port,
|
||||
const std::string &client_cert_path,
|
||||
const std::string &client_key_path) {
|
||||
const static std::regex re(R"(^(https?)://([^:/?#]+)(?::(\d+))?)");
|
||||
|
||||
std::cmatch m;
|
||||
if (std::regex_match(scheme_host_port, m, re)) {
|
||||
auto scheme = m[1].str();
|
||||
auto host = m[2].str();
|
||||
auto port_str = m[3].str();
|
||||
|
||||
auto port = !port_str.empty() ? std::stoi(port_str)
|
||||
: (scheme == "https" ? 443 : 80);
|
||||
|
||||
if (scheme == "https") {
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
is_ssl_ = true;
|
||||
cli_ = std::make_shared<SSLClient>(host.c_str(), port, client_cert_path,
|
||||
client_key_path);
|
||||
#endif
|
||||
} else {
|
||||
cli_ = std::make_shared<Client>(host.c_str(), port, client_cert_path,
|
||||
client_key_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~Client2() {}
|
||||
|
||||
bool is_valid() const { return cli_ != nullptr; }
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path) { return cli_->Get(path); }
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers) {
|
||||
return cli_->Get(path, headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, Progress progress) {
|
||||
return cli_->Get(path, progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
Progress progress) {
|
||||
return cli_->Get(path, headers, progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path,
|
||||
ContentReceiver content_receiver) {
|
||||
return cli_->Get(path, content_receiver);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
ContentReceiver content_receiver) {
|
||||
return cli_->Get(path, headers, content_receiver);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response>
|
||||
Get(const char *path, ContentReceiver content_receiver, Progress progress) {
|
||||
return cli_->Get(path, content_receiver, progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
ContentReceiver content_receiver,
|
||||
Progress progress) {
|
||||
return cli_->Get(path, headers, content_receiver, progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
ResponseHandler response_handler,
|
||||
ContentReceiver content_receiver) {
|
||||
return cli_->Get(path, headers, response_handler, content_receiver);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
ResponseHandler response_handler,
|
||||
ContentReceiver content_receiver,
|
||||
Progress progress) {
|
||||
return cli_->Get(path, headers, response_handler, content_receiver,
|
||||
progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Head(const char *path) { return cli_->Head(path); }
|
||||
|
||||
std::shared_ptr<Response> Head(const char *path, const Headers &headers) {
|
||||
return cli_->Head(path, headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path) { return cli_->Post(path); }
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Post(path, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
|
||||
const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Post(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Post(path, content_length, content_provider, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
|
||||
size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Post(path, headers, content_length, content_provider,
|
||||
content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Params ¶ms) {
|
||||
return cli_->Post(path, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
|
||||
const Params ¶ms) {
|
||||
return cli_->Post(path, headers, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path,
|
||||
const MultipartFormDataItems &items) {
|
||||
return cli_->Post(path, items);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
|
||||
const MultipartFormDataItems &items) {
|
||||
return cli_->Post(path, headers, items);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path) { return cli_->Put(path); }
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Put(path, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const Headers &headers,
|
||||
const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Put(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Put(path, content_length, content_provider, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const Headers &headers,
|
||||
size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Put(path, headers, content_length, content_provider,
|
||||
content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const Params ¶ms) {
|
||||
return cli_->Put(path, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const Headers &headers,
|
||||
const Params ¶ms) {
|
||||
return cli_->Put(path, headers, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Patch(const char *path, const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Patch(path, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Patch(const char *path, const Headers &headers,
|
||||
const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Patch(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Patch(const char *path, size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Patch(path, content_length, content_provider, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Patch(const char *path, const Headers &headers,
|
||||
size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Patch(path, headers, content_length, content_provider,
|
||||
content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Delete(const char *path) {
|
||||
return cli_->Delete(path);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Delete(const char *path, const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Delete(path, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Delete(const char *path, const Headers &headers) {
|
||||
return cli_->Delete(path, headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Delete(const char *path, const Headers &headers,
|
||||
const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Delete(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Options(const char *path) {
|
||||
return cli_->Options(path);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Options(const char *path, const Headers &headers) {
|
||||
return cli_->Options(path, headers);
|
||||
}
|
||||
|
||||
bool send(const Request &req, Response &res) { return cli_->send(req, res); }
|
||||
|
||||
bool send(const std::vector<Request> &requests,
|
||||
std::vector<Response> &responses) {
|
||||
return cli_->send(requests, responses);
|
||||
}
|
||||
|
||||
void stop() { cli_->stop(); }
|
||||
|
||||
Client2 &set_timeout_sec(time_t timeout_sec) {
|
||||
cli_->set_timeout_sec(timeout_sec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_read_timeout(time_t sec, time_t usec) {
|
||||
cli_->set_read_timeout(sec, usec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_keep_alive_max_count(size_t count) {
|
||||
cli_->set_keep_alive_max_count(count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_basic_auth(const char *username, const char *password) {
|
||||
cli_->set_basic_auth(username, password);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
Client2 &set_digest_auth(const char *username, const char *password) {
|
||||
cli_->set_digest_auth(username, password);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
Client2 &set_follow_location(bool on) {
|
||||
cli_->set_follow_location(on);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_compress(bool on) {
|
||||
cli_->set_compress(on);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_interface(const char *intf) {
|
||||
cli_->set_interface(intf);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_proxy(const char *host, int port) {
|
||||
cli_->set_proxy(host, port);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_proxy_basic_auth(const char *username, const char *password) {
|
||||
cli_->set_proxy_basic_auth(username, password);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
Client2 &set_proxy_digest_auth(const char *username, const char *password) {
|
||||
cli_->set_proxy_digest_auth(username, password);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
Client2 &set_logger(Logger logger) {
|
||||
cli_->set_logger(logger);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// SSL
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
Client2 &set_ca_cert_path(const char *ca_cert_file_path,
|
||||
const char *ca_cert_dir_path = nullptr) {
|
||||
dynamic_cast<SSLClient &>(*cli_).set_ca_cert_path(ca_cert_file_path,
|
||||
ca_cert_dir_path);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_ca_cert_store(X509_STORE *ca_cert_store) {
|
||||
dynamic_cast<SSLClient &>(*cli_).set_ca_cert_store(ca_cert_store);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &enable_server_certificate_verification(bool enabled) {
|
||||
dynamic_cast<SSLClient &>(*cli_).enable_server_certificate_verification(
|
||||
enabled);
|
||||
return *this;
|
||||
}
|
||||
|
||||
long get_openssl_verify_result() const {
|
||||
return dynamic_cast<SSLClient &>(*cli_).get_openssl_verify_result();
|
||||
}
|
||||
|
||||
SSL_CTX *ssl_context() const {
|
||||
return dynamic_cast<SSLClient &>(*cli_).ssl_context();
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool is_ssl_ = false;
|
||||
std::shared_ptr<Client> cli_;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -3126,14 +3474,7 @@ inline const std::string &BufferStream::get_buffer() const { return buffer; }
|
||||
} // namespace detail
|
||||
|
||||
// HTTP server implementation
|
||||
inline Server::Server()
|
||||
: keep_alive_max_count_(CPPHTTPLIB_KEEPALIVE_MAX_COUNT),
|
||||
read_timeout_sec_(CPPHTTPLIB_READ_TIMEOUT_SECOND),
|
||||
read_timeout_usec_(CPPHTTPLIB_READ_TIMEOUT_USECOND),
|
||||
write_timeout_sec_(CPPHTTPLIB_WRITE_TIMEOUT_SECOND),
|
||||
write_timeout_usec_(CPPHTTPLIB_WRITE_TIMEOUT_USECOND),
|
||||
payload_max_length_(CPPHTTPLIB_PAYLOAD_MAX_LENGTH), is_running_(false),
|
||||
svr_sock_(INVALID_SOCKET) {
|
||||
inline Server::Server() : is_running_(false), svr_sock_(INVALID_SOCKET) {
|
||||
#ifndef _WIN32
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
@@ -3259,6 +3600,11 @@ inline void Server::set_write_timeout(time_t sec, time_t usec) {
|
||||
write_timeout_usec_ = usec;
|
||||
}
|
||||
|
||||
inline void Server::set_idle_interval(time_t sec, time_t usec) {
|
||||
idle_interval_sec_ = sec;
|
||||
idle_interval_usec_ = usec;
|
||||
}
|
||||
|
||||
inline void Server::set_payload_max_length(size_t length) {
|
||||
payload_max_length_ = length;
|
||||
}
|
||||
@@ -3631,19 +3977,19 @@ inline bool Server::listen_internal() {
|
||||
{
|
||||
std::unique_ptr<TaskQueue> task_queue(new_task_queue());
|
||||
|
||||
for (;;) {
|
||||
if (svr_sock_ == INVALID_SOCKET) {
|
||||
// The server socket was closed by 'stop' method.
|
||||
break;
|
||||
while (svr_sock_ != INVALID_SOCKET) {
|
||||
#ifndef _WIN32
|
||||
if (idle_interval_sec_ > 0 || idle_interval_usec_ > 0) {
|
||||
#endif
|
||||
auto val = detail::select_read(svr_sock_, idle_interval_sec_,
|
||||
idle_interval_usec_);
|
||||
if (val == 0) { // Timeout
|
||||
task_queue->on_idle();
|
||||
continue;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
}
|
||||
|
||||
auto val = detail::select_read(svr_sock_, 0, 100000);
|
||||
|
||||
if (val == 0) { // Timeout
|
||||
task_queue->on_idle();
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif
|
||||
socket_t sock = accept(svr_sock_, nullptr, nullptr);
|
||||
|
||||
if (sock == INVALID_SOCKET) {
|
||||
@@ -5216,339 +5562,6 @@ inline bool SSLClient::check_host_name(const char *pattern,
|
||||
}
|
||||
#endif
|
||||
|
||||
class Client2 {
|
||||
public:
|
||||
explicit Client2(const char *scheme_host_port)
|
||||
: Client2(scheme_host_port, std::string(), std::string()) {}
|
||||
|
||||
explicit Client2(const char *scheme_host_port,
|
||||
const std::string &client_cert_path,
|
||||
const std::string &client_key_path) {
|
||||
const static std::regex re(R"(^(https?)://([^:/?#]+)(?::(\d+))?)");
|
||||
|
||||
std::cmatch m;
|
||||
if (std::regex_match(scheme_host_port, m, re)) {
|
||||
auto scheme = m[1].str();
|
||||
auto host = m[2].str();
|
||||
auto port_str = m[3].str();
|
||||
|
||||
auto port = !port_str.empty() ? std::stoi(port_str)
|
||||
: (scheme == "https" ? 443 : 80);
|
||||
|
||||
if (scheme == "https") {
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
is_ssl_ = true;
|
||||
cli_ = std::make_shared<SSLClient>(host.c_str(), port, client_cert_path,
|
||||
client_key_path);
|
||||
#endif
|
||||
} else {
|
||||
cli_ = std::make_shared<Client>(host.c_str(), port, client_cert_path,
|
||||
client_key_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~Client2() {}
|
||||
|
||||
bool is_valid() const { return cli_ != nullptr; }
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path) { return cli_->Get(path); }
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers) {
|
||||
return cli_->Get(path, headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, Progress progress) {
|
||||
return cli_->Get(path, progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
Progress progress) {
|
||||
return cli_->Get(path, headers, progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path,
|
||||
ContentReceiver content_receiver) {
|
||||
return cli_->Get(path, content_receiver);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
ContentReceiver content_receiver) {
|
||||
return cli_->Get(path, headers, content_receiver);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response>
|
||||
Get(const char *path, ContentReceiver content_receiver, Progress progress) {
|
||||
return cli_->Get(path, content_receiver, progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
ContentReceiver content_receiver,
|
||||
Progress progress) {
|
||||
return cli_->Get(path, headers, content_receiver, progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
ResponseHandler response_handler,
|
||||
ContentReceiver content_receiver) {
|
||||
return cli_->Get(path, headers, response_handler, content_receiver);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Get(const char *path, const Headers &headers,
|
||||
ResponseHandler response_handler,
|
||||
ContentReceiver content_receiver,
|
||||
Progress progress) {
|
||||
return cli_->Get(path, headers, response_handler, content_receiver,
|
||||
progress);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Head(const char *path) { return cli_->Head(path); }
|
||||
|
||||
std::shared_ptr<Response> Head(const char *path, const Headers &headers) {
|
||||
return cli_->Head(path, headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path) { return cli_->Post(path); }
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Post(path, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
|
||||
const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Post(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Post(path, content_length, content_provider, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
|
||||
size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Post(path, headers, content_length, content_provider,
|
||||
content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Params ¶ms) {
|
||||
return cli_->Post(path, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
|
||||
const Params ¶ms) {
|
||||
return cli_->Post(path, headers, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path,
|
||||
const MultipartFormDataItems &items) {
|
||||
return cli_->Post(path, items);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
|
||||
const MultipartFormDataItems &items) {
|
||||
return cli_->Post(path, headers, items);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path) { return cli_->Put(path); }
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Put(path, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const Headers &headers,
|
||||
const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Put(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Put(path, content_length, content_provider, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const Headers &headers,
|
||||
size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Put(path, headers, content_length, content_provider,
|
||||
content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const Params ¶ms) {
|
||||
return cli_->Put(path, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Put(const char *path, const Headers &headers,
|
||||
const Params ¶ms) {
|
||||
return cli_->Put(path, headers, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Patch(const char *path, const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Patch(path, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Patch(const char *path, const Headers &headers,
|
||||
const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Patch(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Patch(const char *path, size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Patch(path, content_length, content_provider, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Patch(const char *path, const Headers &headers,
|
||||
size_t content_length,
|
||||
ContentProvider content_provider,
|
||||
const char *content_type) {
|
||||
return cli_->Patch(path, headers, content_length, content_provider,
|
||||
content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Delete(const char *path) {
|
||||
return cli_->Delete(path);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Delete(const char *path, const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Delete(path, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Delete(const char *path, const Headers &headers) {
|
||||
return cli_->Delete(path, headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Delete(const char *path, const Headers &headers,
|
||||
const std::string &body,
|
||||
const char *content_type) {
|
||||
return cli_->Delete(path, headers, body, content_type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Options(const char *path) {
|
||||
return cli_->Options(path);
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> Options(const char *path, const Headers &headers) {
|
||||
return cli_->Options(path, headers);
|
||||
}
|
||||
|
||||
bool send(const Request &req, Response &res) { return cli_->send(req, res); }
|
||||
|
||||
bool send(const std::vector<Request> &requests,
|
||||
std::vector<Response> &responses) {
|
||||
return cli_->send(requests, responses);
|
||||
}
|
||||
|
||||
void stop() { cli_->stop(); }
|
||||
|
||||
Client2 &set_timeout_sec(time_t timeout_sec) {
|
||||
cli_->set_timeout_sec(timeout_sec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_read_timeout(time_t sec, time_t usec) {
|
||||
cli_->set_read_timeout(sec, usec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_keep_alive_max_count(size_t count) {
|
||||
cli_->set_keep_alive_max_count(count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_basic_auth(const char *username, const char *password) {
|
||||
cli_->set_basic_auth(username, password);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
Client2 &set_digest_auth(const char *username, const char *password) {
|
||||
cli_->set_digest_auth(username, password);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
Client2 &set_follow_location(bool on) {
|
||||
cli_->set_follow_location(on);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_compress(bool on) {
|
||||
cli_->set_compress(on);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_interface(const char *intf) {
|
||||
cli_->set_interface(intf);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_proxy(const char *host, int port) {
|
||||
cli_->set_proxy(host, port);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_proxy_basic_auth(const char *username, const char *password) {
|
||||
cli_->set_proxy_basic_auth(username, password);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
Client2 &set_proxy_digest_auth(const char *username, const char *password) {
|
||||
cli_->set_proxy_digest_auth(username, password);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
Client2 &set_logger(Logger logger) {
|
||||
cli_->set_logger(logger);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// SSL
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
Client2 &set_ca_cert_path(const char *ca_cert_file_path,
|
||||
const char *ca_cert_dir_path = nullptr) {
|
||||
dynamic_cast<SSLClient &>(*cli_).set_ca_cert_path(ca_cert_file_path,
|
||||
ca_cert_dir_path);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &set_ca_cert_store(X509_STORE *ca_cert_store) {
|
||||
dynamic_cast<SSLClient &>(*cli_).set_ca_cert_store(ca_cert_store);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Client2 &enable_server_certificate_verification(bool enabled) {
|
||||
dynamic_cast<SSLClient &>(*cli_).enable_server_certificate_verification(
|
||||
enabled);
|
||||
return *this;
|
||||
}
|
||||
|
||||
long get_openssl_verify_result() const {
|
||||
return dynamic_cast<SSLClient &>(*cli_).get_openssl_verify_result();
|
||||
}
|
||||
|
||||
SSL_CTX *ssl_context() const {
|
||||
return dynamic_cast<SSLClient &>(*cli_).ssl_context();
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool is_ssl_ = false;
|
||||
std::shared_ptr<Client> cli_;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
#undef HANDLE_EINTR
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Generates a macro to auto-configure everything
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
# We add find_dependency calls here to not make the end-user have to call them.
|
||||
find_dependency(Threads REQUIRED)
|
||||
if(@HTTPLIB_REQUIRE_OPENSSL@)
|
||||
find_dependency(OpenSSL @_HTTPLIB_OPENSSL_MIN_VER@ REQUIRED)
|
||||
# Lets you check if these options were correctly enabled for your install
|
||||
set(HTTPLIB_IS_USING_OPENSSL TRUE)
|
||||
elseif(@HTTPLIB_USE_OPENSSL_IF_AVAILABLE@)
|
||||
# Look quietly since it's optional
|
||||
find_dependency(OpenSSL @_HTTPLIB_OPENSSL_MIN_VER@ QUIET)
|
||||
# Lets you check if these options were correctly enabled for your install
|
||||
set(HTTPLIB_IS_USING_OPENSSL @OPENSSL_FOUND@)
|
||||
else()
|
||||
set(HTTPLIB_IS_USING_OPENSSL FALSE)
|
||||
endif()
|
||||
if(@HTTPLIB_REQUIRE_ZLIB@)
|
||||
find_dependency(ZLIB REQUIRED)
|
||||
# Lets you check if these options were correctly enabled for your install
|
||||
set(HTTPLIB_IS_USING_ZLIB TRUE)
|
||||
elseif(@HTTPLIB_USE_ZLIB_IF_AVAILABLE@)
|
||||
# Look quietly since it's optional
|
||||
find_dependency(ZLIB QUIET)
|
||||
# Lets you check if these options were correctly enabled for your install
|
||||
set(HTTPLIB_IS_USING_ZLIB @ZLIB_FOUND@)
|
||||
else()
|
||||
set(HTTPLIB_IS_USING_ZLIB FALSE)
|
||||
endif()
|
||||
|
||||
# Lets the end-user find the header path if needed
|
||||
# This is helpful if you're using Cmake's pre-compiled header feature
|
||||
set_and_check(HTTPLIB_HEADER_PATH "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@/httplib.h")
|
||||
|
||||
# Brings in the target library
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/httplibTargets.cmake")
|
||||
Reference in New Issue
Block a user