mirror of
https://github.com/yhirose/cpp-httplib
synced 2026-06-08 18:30:49 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d3076f5a70 | |||
| ed129f057f | |||
| eab5ea01d7 | |||
| 3e287b3a26 | |||
| 4f33637b43 | |||
| 698a1e51ec | |||
| 27c0e1186c | |||
| c54c71a3e5 | |||
| 3409c00e6f | |||
| f8ef5fab64 | |||
| 5b397d455d | |||
| f977558a28 | |||
| c2e156e0e0 | |||
| 7aba2938d3 | |||
| d587548250 | |||
| 21f9c51556 | |||
| 985ceba525 | |||
| e62a4b02e5 | |||
| ff34749572 | |||
| e5804d4a50 | |||
| 3956a2b790 | |||
| b33aa52dc2 | |||
| 76230db97f |
+36
-18
@@ -6,8 +6,10 @@
|
||||
* HTTPLIB_REQUIRE_OPENSSL (default off)
|
||||
* HTTPLIB_REQUIRE_ZLIB (default off)
|
||||
* HTTPLIB_USE_BROTLI_IF_AVAILABLE (default on)
|
||||
* HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on)
|
||||
* HTTPLIB_REQUIRE_BROTLI (default off)
|
||||
* HTTPLIB_COMPILE (default off)
|
||||
* HTTPLIB_INSTALL (default on)
|
||||
* HTTPLIB_TEST (default off)
|
||||
* BROTLI_USE_STATIC_LIBS - tells Cmake to use the static Brotli libs (only works if you have them installed).
|
||||
* OPENSSL_USE_STATIC_LIBS - tells Cmake to use the static OpenSSL libs (only works if you have them installed).
|
||||
@@ -43,6 +45,7 @@
|
||||
* HTTPLIB_IS_USING_OPENSSL - a bool for if OpenSSL support is enabled.
|
||||
* HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled.
|
||||
* HTTPLIB_IS_USING_BROTLI - a bool for if Brotli support is enabled.
|
||||
* HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN - a bool for if support of loading system certs from the Apple Keychain is enabled.
|
||||
* HTTPLIB_IS_COMPILED - a bool for if the library is compiled, or otherwise header-only.
|
||||
* HTTPLIB_INCLUDE_DIR - the root path to httplib's header (e.g. /usr/include).
|
||||
* HTTPLIB_LIBRARY - the full path to the library if compiled (e.g. /usr/lib/libhttplib.so).
|
||||
@@ -72,6 +75,10 @@ string(REGEX MATCH "([0-9]+\\.?)+" _httplib_version "${_raw_version_string}")
|
||||
|
||||
project(httplib VERSION ${_httplib_version} LANGUAGES CXX)
|
||||
|
||||
# Lets you disable C++ exception during CMake configure time.
|
||||
# The value is used in the install CMake config file.
|
||||
option(HTTPLIB_NO_EXCEPTIONS "Disable the use of C++ exceptions" OFF)
|
||||
|
||||
# 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")
|
||||
@@ -85,6 +92,8 @@ option(HTTPLIB_USE_OPENSSL_IF_AVAILABLE "Uses OpenSSL (if available) to enable H
|
||||
option(HTTPLIB_USE_ZLIB_IF_AVAILABLE "Uses ZLIB (if available) to enable Zlib compression support." ON)
|
||||
# Lets you compile the program as a regular library instead of header-only
|
||||
option(HTTPLIB_COMPILE "If ON, uses a Python script to split the header into a compilable header & source file (requires Python v3)." OFF)
|
||||
# Lets you disable the installation (useful when fetched from another CMake project)
|
||||
option(HTTPLIB_INSTALL "Enables the installation target" ON)
|
||||
# Just setting this variable here for people building in-tree
|
||||
if(HTTPLIB_COMPILE)
|
||||
set(HTTPLIB_IS_COMPILED TRUE)
|
||||
@@ -92,6 +101,7 @@ endif()
|
||||
option(HTTPLIB_TEST "Enables testing and builds tests" OFF)
|
||||
option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF)
|
||||
option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON)
|
||||
option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system certs from the Apple Keychain." ON)
|
||||
# Defaults to static library
|
||||
option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF)
|
||||
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
|
||||
@@ -137,6 +147,10 @@ if(Brotli_FOUND)
|
||||
set(HTTPLIB_IS_USING_BROTLI TRUE)
|
||||
endif()
|
||||
|
||||
if(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN)
|
||||
set(HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN TRUE)
|
||||
endif()
|
||||
|
||||
# Used for default, common dirs that the end-user can change (if needed)
|
||||
# like CMAKE_INSTALL_INCLUDEDIR or CMAKE_INSTALL_DATADIR
|
||||
include(GNUInstallDirs)
|
||||
@@ -207,7 +221,7 @@ target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
$<$<PLATFORM_ID:Windows>:crypt32>
|
||||
$<$<PLATFORM_ID:Windows>:cryptui>
|
||||
# Needed for API from MacOS Security framework
|
||||
"$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>>:-framework CoreFoundation -framework Security>"
|
||||
"$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN}>>:-framework CoreFoundation -framework Security>"
|
||||
# Can't put multiple targets in a single generator expression or it bugs out.
|
||||
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::common>
|
||||
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::encoder>
|
||||
@@ -219,9 +233,11 @@ target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
|
||||
# Set the definitions to enable optional features
|
||||
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
$<$<BOOL:${HTTPLIB_NO_EXCEPTIONS}>:CPPHTTPLIB_NO_EXCEPTIONS>
|
||||
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:CPPHTTPLIB_BROTLI_SUPPORT>
|
||||
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
|
||||
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_SUPPORT>
|
||||
$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN}>>:CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN>
|
||||
)
|
||||
|
||||
# CMake configuration files installation directory
|
||||
@@ -254,31 +270,33 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
# 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
|
||||
)
|
||||
if(HTTPLIB_INSTALL)
|
||||
# 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
|
||||
)
|
||||
|
||||
install(FILES "${_httplib_build_includedir}/httplib.h" TYPE INCLUDE)
|
||||
install(FILES "${_httplib_build_includedir}/httplib.h" TYPE INCLUDE)
|
||||
|
||||
install(FILES
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
# Install it so it can be used later by the httplibConfig.cmake file.
|
||||
# Put it in the same dir as our config file instead of a global path so we don't potentially stomp on other packages.
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindBrotli.cmake"
|
||||
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
|
||||
)
|
||||
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}
|
||||
)
|
||||
# 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}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(HTTPLIB_TEST)
|
||||
include(CTest)
|
||||
|
||||
@@ -54,7 +54,8 @@ SSL Support
|
||||
SSL support is available with `CPPHTTPLIB_OPENSSL_SUPPORT`. `libssl` and `libcrypto` should be linked.
|
||||
|
||||
NOTE: cpp-httplib currently supports only version 1.1.1 and 3.0.
|
||||
NOTE for macOS: cpp-httplib now uses system certs. `CoreFoundation` and `Security` should be linked with `-framework`.
|
||||
|
||||
NOTE for macOS: cpp-httplib now can use system certs with `CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN`. `CoreFoundation` and `Security` should be linked with `-framework`.
|
||||
|
||||
```c++
|
||||
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
@@ -75,7 +76,7 @@ cli.set_ca_cert_path("./ca-bundle.crt");
|
||||
cli.enable_server_certificate_verification(false);
|
||||
```
|
||||
|
||||
Note: When using SSL, it seems impossible to avoid SIGPIPE in all cases, since on some operating systems, SIGPIPE can only be suppressed on a per-message basis, but there is no way to make the OpenSSL library do so for its internal communications. If your program needs to avoid being terminated on SIGPIPE, the only fully general way might be to set up a signal handler for SIGPIPE to handle or ignore it yourself.
|
||||
NOTE: When using SSL, it seems impossible to avoid SIGPIPE in all cases, since on some operating systems, SIGPIPE can only be suppressed on a per-message basis, but there is no way to make the OpenSSL library do so for its internal communications. If your program needs to avoid being terminated on SIGPIPE, the only fully general way might be to set up a signal handler for SIGPIPE to handle or ignore it yourself.
|
||||
|
||||
Server
|
||||
------
|
||||
@@ -834,9 +835,9 @@ Include `httplib.h` before `Windows.h` or include `Windows.h` by defining `WIN32
|
||||
#include <httplib.h>
|
||||
```
|
||||
|
||||
Note: cpp-httplib officially supports only the latest Visual Studio. It might work with former versions of Visual Studio, but I can no longer verify it. Pull requests are always welcome for the older versions of Visual Studio unless they break the C++11 conformance.
|
||||
NOTE: cpp-httplib officially supports only the latest Visual Studio. It might work with former versions of Visual Studio, but I can no longer verify it. Pull requests are always welcome for the older versions of Visual Studio unless they break the C++11 conformance.
|
||||
|
||||
Note: Windows 8 or lower, Visual Studio 2013 or lower, and Cygwin on Windows are not supported.
|
||||
NOTE: Windows 8 or lower, Visual Studio 2013 or lower, and Cygwin on Windows are not supported.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef CPPHTTPLIB_HTTPLIB_H
|
||||
#define CPPHTTPLIB_HTTPLIB_H
|
||||
|
||||
#define CPPHTTPLIB_VERSION "0.12.2"
|
||||
#define CPPHTTPLIB_VERSION "0.12.6"
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
@@ -172,9 +172,15 @@ using socket_t = SOCKET;
|
||||
#else // not _WIN32
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#ifndef _AIX
|
||||
#if !defined(_AIX) && !defined(__MVS__)
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#ifdef __MVS__
|
||||
#include <strings.h>
|
||||
#ifndef NI_MAXHOST
|
||||
#define NI_MAXHOST 1025
|
||||
#endif
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -223,6 +229,7 @@ using socket_t = int;
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
#ifdef _WIN32
|
||||
@@ -239,10 +246,13 @@ using socket_t = int;
|
||||
#pragma comment(lib, "crypt32.lib")
|
||||
#pragma comment(lib, "cryptui.lib")
|
||||
#endif
|
||||
#elif defined(__APPLE__) // _WIN32
|
||||
#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_OSX
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
#endif // __APPLE__
|
||||
#endif // TARGET_OS_OSX
|
||||
#endif // _WIN32
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
@@ -314,8 +324,8 @@ struct ci {
|
||||
// This is based on
|
||||
// "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189".
|
||||
|
||||
template <typename EF> struct scope_exit {
|
||||
explicit scope_exit(EF &&f)
|
||||
struct scope_exit {
|
||||
explicit scope_exit(std::function<void(void)> &&f)
|
||||
: exit_function(std::move(f)), execute_on_destruction{true} {}
|
||||
|
||||
scope_exit(scope_exit &&rhs)
|
||||
@@ -335,7 +345,7 @@ private:
|
||||
void operator=(const scope_exit &) = delete;
|
||||
scope_exit &operator=(scope_exit &&) = delete;
|
||||
|
||||
EF exit_function;
|
||||
std::function<void(void)> exit_function;
|
||||
bool execute_on_destruction;
|
||||
};
|
||||
|
||||
@@ -740,6 +750,7 @@ public:
|
||||
bool listen(const std::string &host, int port, int socket_flags = 0);
|
||||
|
||||
bool is_running() const;
|
||||
void wait_until_ready() const;
|
||||
void stop();
|
||||
|
||||
std::function<TaskQueue *(void)> new_task_queue;
|
||||
@@ -749,7 +760,7 @@ protected:
|
||||
bool &connection_closed,
|
||||
const std::function<void(Request &)> &setup_request);
|
||||
|
||||
std::atomic<socket_t> svr_sock_;
|
||||
std::atomic<socket_t> svr_sock_{INVALID_SOCKET};
|
||||
size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
|
||||
time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
|
||||
time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
|
||||
@@ -813,7 +824,8 @@ private:
|
||||
};
|
||||
std::vector<MountPointEntry> base_dirs_;
|
||||
|
||||
std::atomic<bool> is_running_;
|
||||
std::atomic<bool> is_running_{false};
|
||||
std::atomic<bool> done_{false};
|
||||
std::map<std::string, std::string> file_extension_and_mimetype_map_;
|
||||
Handler file_request_handler_;
|
||||
Handlers get_handlers_;
|
||||
@@ -1112,6 +1124,7 @@ public:
|
||||
void set_ca_cert_path(const std::string &ca_cert_file_path,
|
||||
const std::string &ca_cert_dir_path = std::string());
|
||||
void set_ca_cert_store(X509_STORE *ca_cert_store);
|
||||
X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size);
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
@@ -1492,6 +1505,7 @@ public:
|
||||
const std::string &ca_cert_dir_path = std::string());
|
||||
|
||||
void set_ca_cert_store(X509_STORE *ca_cert_store);
|
||||
void load_ca_cert_store(const char *ca_cert, std::size_t size);
|
||||
|
||||
long get_openssl_verify_result() const;
|
||||
|
||||
@@ -1551,6 +1565,7 @@ public:
|
||||
bool is_valid() const override;
|
||||
|
||||
void set_ca_cert_store(X509_STORE *ca_cert_store);
|
||||
void load_ca_cert_store(const char *ca_cert, std::size_t size);
|
||||
|
||||
long get_openssl_verify_result() const;
|
||||
|
||||
@@ -2665,7 +2680,7 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
|
||||
|
||||
auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol);
|
||||
if (sock != INVALID_SOCKET) {
|
||||
sockaddr_un addr;
|
||||
sockaddr_un addr{};
|
||||
addr.sun_family = AF_UNIX;
|
||||
std::copy(host.begin(), host.end(), addr.sun_path);
|
||||
|
||||
@@ -2723,7 +2738,10 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
|
||||
if (sock == INVALID_SOCKET) { continue; }
|
||||
|
||||
#ifndef _WIN32
|
||||
if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { continue; }
|
||||
if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) {
|
||||
close_socket(sock);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tcp_nodelay) {
|
||||
@@ -2796,7 +2814,7 @@ inline bool bind_ip_address(socket_t sock, const std::string &host) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined _WIN32 && !defined ANDROID && !defined _AIX
|
||||
#if !defined _WIN32 && !defined ANDROID && !defined _AIX && !defined __MVS__
|
||||
#define USE_IF2IP
|
||||
#endif
|
||||
|
||||
@@ -4510,7 +4528,8 @@ inline bool load_system_certs_on_windows(X509_STORE *store) {
|
||||
|
||||
return result;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
|
||||
#if TARGET_OS_OSX
|
||||
template <typename T>
|
||||
using CFObjectPtr =
|
||||
std::unique_ptr<typename std::remove_pointer<T>::type, void (*)(CFTypeRef)>;
|
||||
@@ -4585,7 +4604,7 @@ inline bool add_certs_to_x509_store(CFArrayRef certs, X509_STORE *store) {
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool load_system_certs_on_apple(X509_STORE *store) {
|
||||
inline bool load_system_certs_on_macos(X509_STORE *store) {
|
||||
auto result = false;
|
||||
CFObjectPtr<CFArrayRef> certs(nullptr, cf_object_ptr_deleter);
|
||||
if (retrieve_certs_from_keychain(certs) && certs) {
|
||||
@@ -4598,8 +4617,9 @@ inline bool load_system_certs_on_apple(X509_STORE *store) {
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif // TARGET_OS_OSX
|
||||
#endif // _WIN32
|
||||
#endif // CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
|
||||
#ifdef _WIN32
|
||||
class WSInit {
|
||||
@@ -4936,10 +4956,9 @@ inline void Response::set_content(const std::string &s,
|
||||
inline void Response::set_content_provider(
|
||||
size_t in_length, const std::string &content_type, ContentProvider provider,
|
||||
ContentProviderResourceReleaser resource_releaser) {
|
||||
assert(in_length > 0);
|
||||
set_header("Content-Type", content_type);
|
||||
content_length_ = in_length;
|
||||
content_provider_ = std::move(provider);
|
||||
if (in_length > 0) { content_provider_ = std::move(provider); }
|
||||
content_provider_resource_releaser_ = resource_releaser;
|
||||
is_chunked_content_provider_ = false;
|
||||
}
|
||||
@@ -5116,8 +5135,7 @@ inline const std::string &BufferStream::get_buffer() const { return buffer; }
|
||||
// HTTP server implementation
|
||||
inline Server::Server()
|
||||
: new_task_queue(
|
||||
[] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }),
|
||||
svr_sock_(INVALID_SOCKET), is_running_(false) {
|
||||
[] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }) {
|
||||
#ifndef _WIN32
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
@@ -5264,7 +5282,6 @@ inline Server &Server::set_logger(Logger logger) {
|
||||
inline Server &
|
||||
Server::set_expect_100_continue_handler(Expect100ContinueHandler handler) {
|
||||
expect_100_continue_handler_ = std::move(handler);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -5330,15 +5347,25 @@ inline int Server::bind_to_any_port(const std::string &host, int socket_flags) {
|
||||
return bind_internal(host, 0, socket_flags);
|
||||
}
|
||||
|
||||
inline bool Server::listen_after_bind() { return listen_internal(); }
|
||||
inline bool Server::listen_after_bind() {
|
||||
auto se = detail::scope_exit([&]() { done_ = true; });
|
||||
return listen_internal();
|
||||
}
|
||||
|
||||
inline bool Server::listen(const std::string &host, int port,
|
||||
int socket_flags) {
|
||||
auto se = detail::scope_exit([&]() { done_ = true; });
|
||||
return bind_to_port(host, port, socket_flags) && listen_internal();
|
||||
}
|
||||
|
||||
inline bool Server::is_running() const { return is_running_; }
|
||||
|
||||
inline void Server::wait_until_ready() const {
|
||||
while (!is_running() && !done_) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{1});
|
||||
}
|
||||
}
|
||||
|
||||
inline void Server::stop() {
|
||||
if (is_running_) {
|
||||
assert(svr_sock_ != INVALID_SOCKET);
|
||||
@@ -5729,6 +5756,7 @@ inline int Server::bind_internal(const std::string &host, int port,
|
||||
inline bool Server::listen_internal() {
|
||||
auto ret = true;
|
||||
is_running_ = true;
|
||||
auto se = detail::scope_exit([&]() { is_running_ = false; });
|
||||
|
||||
{
|
||||
std::unique_ptr<TaskQueue> task_queue(new_task_queue());
|
||||
@@ -5800,7 +5828,6 @@ inline bool Server::listen_internal() {
|
||||
task_queue->shutdown();
|
||||
}
|
||||
|
||||
is_running_ = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5907,8 +5934,8 @@ inline void Server::apply_ranges(const Request &req, Response &res,
|
||||
res.headers.erase(it);
|
||||
}
|
||||
|
||||
res.headers.emplace("Content-Type",
|
||||
"multipart/byteranges; boundary=" + boundary);
|
||||
res.set_header("Content-Type",
|
||||
"multipart/byteranges; boundary=" + boundary);
|
||||
}
|
||||
|
||||
auto type = detail::encoding_type(req, res);
|
||||
@@ -6410,7 +6437,7 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
||||
auto ret = false;
|
||||
auto close_connection = !keep_alive_;
|
||||
|
||||
auto se = detail::scope_exit<std::function<void(void)>>([&]() {
|
||||
auto se = detail::scope_exit([&]() {
|
||||
// Briefly lock mutex in order to mark that a request is no longer ongoing
|
||||
std::lock_guard<std::mutex> guard(socket_mutex_);
|
||||
socket_requests_in_flight_ -= 1;
|
||||
@@ -6598,32 +6625,32 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
|
||||
// Prepare additional headers
|
||||
if (close_connection) {
|
||||
if (!req.has_header("Connection")) {
|
||||
req.headers.emplace("Connection", "close");
|
||||
req.set_header("Connection", "close");
|
||||
}
|
||||
}
|
||||
|
||||
if (!req.has_header("Host")) {
|
||||
if (is_ssl()) {
|
||||
if (port_ == 443) {
|
||||
req.headers.emplace("Host", host_);
|
||||
req.set_header("Host", host_);
|
||||
} else {
|
||||
req.headers.emplace("Host", host_and_port_);
|
||||
req.set_header("Host", host_and_port_);
|
||||
}
|
||||
} else {
|
||||
if (port_ == 80) {
|
||||
req.headers.emplace("Host", host_);
|
||||
req.set_header("Host", host_);
|
||||
} else {
|
||||
req.headers.emplace("Host", host_and_port_);
|
||||
req.set_header("Host", host_and_port_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!req.has_header("Accept")) { req.headers.emplace("Accept", "*/*"); }
|
||||
if (!req.has_header("Accept")) { req.set_header("Accept", "*/*"); }
|
||||
|
||||
#ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT
|
||||
if (!req.has_header("User-Agent")) {
|
||||
auto agent = std::string("cpp-httplib/") + CPPHTTPLIB_VERSION;
|
||||
req.headers.emplace("User-Agent", agent);
|
||||
req.set_header("User-Agent", agent);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6632,23 +6659,23 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
|
||||
if (!req.is_chunked_content_provider_) {
|
||||
if (!req.has_header("Content-Length")) {
|
||||
auto length = std::to_string(req.content_length_);
|
||||
req.headers.emplace("Content-Length", length);
|
||||
req.set_header("Content-Length", length);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (req.method == "POST" || req.method == "PUT" ||
|
||||
req.method == "PATCH") {
|
||||
req.headers.emplace("Content-Length", "0");
|
||||
req.set_header("Content-Length", "0");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!req.has_header("Content-Type")) {
|
||||
req.headers.emplace("Content-Type", "text/plain");
|
||||
req.set_header("Content-Type", "text/plain");
|
||||
}
|
||||
|
||||
if (!req.has_header("Content-Length")) {
|
||||
auto length = std::to_string(req.body.size());
|
||||
req.headers.emplace("Content-Length", length);
|
||||
req.set_header("Content-Length", length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6716,12 +6743,10 @@ inline std::unique_ptr<Response> ClientImpl::send_with_content_provider(
|
||||
ContentProvider content_provider,
|
||||
ContentProviderWithoutLength content_provider_without_length,
|
||||
const std::string &content_type, Error &error) {
|
||||
if (!content_type.empty()) {
|
||||
req.headers.emplace("Content-Type", content_type);
|
||||
}
|
||||
if (!content_type.empty()) { req.set_header("Content-Type", content_type); }
|
||||
|
||||
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
|
||||
if (compress_) { req.headers.emplace("Content-Encoding", "gzip"); }
|
||||
if (compress_) { req.set_header("Content-Encoding", "gzip"); }
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
|
||||
@@ -6782,10 +6807,9 @@ inline std::unique_ptr<Response> ClientImpl::send_with_content_provider(
|
||||
req.content_provider_ = detail::ContentProviderAdapter(
|
||||
std::move(content_provider_without_length));
|
||||
req.is_chunked_content_provider_ = true;
|
||||
req.headers.emplace("Transfer-Encoding", "chunked");
|
||||
req.set_header("Transfer-Encoding", "chunked");
|
||||
} else {
|
||||
req.body.assign(body, content_length);
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7405,9 +7429,7 @@ inline Result ClientImpl::Delete(const std::string &path,
|
||||
req.headers = headers;
|
||||
req.path = path;
|
||||
|
||||
if (!content_type.empty()) {
|
||||
req.headers.emplace("Content-Type", content_type);
|
||||
}
|
||||
if (!content_type.empty()) { req.set_header("Content-Type", content_type); }
|
||||
req.body.assign(body, content_length);
|
||||
|
||||
return send_(std::move(req));
|
||||
@@ -7557,9 +7579,7 @@ inline void ClientImpl::set_proxy_digest_auth(const std::string &username,
|
||||
proxy_digest_auth_username_ = username;
|
||||
proxy_digest_auth_password_ = password;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
inline void ClientImpl::set_ca_cert_path(const std::string &ca_cert_file_path,
|
||||
const std::string &ca_cert_dir_path) {
|
||||
ca_cert_file_path_ = ca_cert_file_path;
|
||||
@@ -7571,9 +7591,34 @@ inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
||||
ca_cert_store_ = ca_cert_store;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
inline X509_STORE *ClientImpl::create_ca_cert_store(const char *ca_cert,
|
||||
std::size_t size) {
|
||||
auto mem = BIO_new_mem_buf(ca_cert, static_cast<int>(size));
|
||||
if (!mem) return nullptr;
|
||||
|
||||
auto inf = PEM_X509_INFO_read_bio(mem, nullptr, nullptr, nullptr);
|
||||
if (!inf) {
|
||||
BIO_free_all(mem);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto cts = X509_STORE_new();
|
||||
if (cts) {
|
||||
for (auto first = 0, last = sk_X509_INFO_num(inf); first < last; ++first) {
|
||||
auto itmp = sk_X509_INFO_value(inf, first);
|
||||
if (!itmp) { continue; }
|
||||
|
||||
if (itmp->x509) { X509_STORE_add_cert(cts, itmp->x509); }
|
||||
if (itmp->crl) { X509_STORE_add_crl(cts, itmp->crl); }
|
||||
}
|
||||
}
|
||||
|
||||
sk_X509_INFO_pop_free(inf, X509_INFO_free);
|
||||
BIO_free_all(mem);
|
||||
return cts;
|
||||
}
|
||||
|
||||
inline void ClientImpl::enable_server_certificate_verification(bool enabled) {
|
||||
server_certificate_verification_ = enabled;
|
||||
}
|
||||
@@ -7971,6 +8016,11 @@ inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void SSLClient::load_ca_cert_store(const char *ca_cert,
|
||||
std::size_t size) {
|
||||
set_ca_cert_store(ClientImpl::create_ca_cert_store(ca_cert, size));
|
||||
}
|
||||
|
||||
inline long SSLClient::get_openssl_verify_result() const {
|
||||
return verify_result_;
|
||||
}
|
||||
@@ -8059,9 +8109,11 @@ inline bool SSLClient::load_certs() {
|
||||
#ifdef _WIN32
|
||||
loaded =
|
||||
detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_));
|
||||
#elif defined(__APPLE__)
|
||||
loaded = detail::load_system_certs_on_apple(SSL_CTX_get_cert_store(ctx_));
|
||||
#endif
|
||||
#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
|
||||
#if TARGET_OS_OSX
|
||||
loaded = detail::load_system_certs_on_macos(SSL_CTX_get_cert_store(ctx_));
|
||||
#endif // TARGET_OS_OSX
|
||||
#endif // _WIN32
|
||||
if (!loaded) { SSL_CTX_set_default_verify_paths(ctx_); }
|
||||
}
|
||||
});
|
||||
@@ -8734,7 +8786,9 @@ inline void Client::enable_server_certificate_verification(bool enabled) {
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void Client::set_logger(Logger logger) { cli_->set_logger(logger); }
|
||||
inline void Client::set_logger(Logger logger) {
|
||||
cli_->set_logger(std::move(logger));
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
inline void Client::set_ca_cert_path(const std::string &ca_cert_file_path,
|
||||
@@ -8750,6 +8804,10 @@ inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void Client::load_ca_cert_store(const char *ca_cert, std::size_t size) {
|
||||
set_ca_cert_store(cli_->create_ca_cert_store(ca_cert, size));
|
||||
}
|
||||
|
||||
inline long Client::get_openssl_verify_result() const {
|
||||
if (is_ssl_) {
|
||||
return static_cast<SSLClient &>(*cli_).get_openssl_verify_result();
|
||||
|
||||
+5
-1
@@ -35,7 +35,11 @@ if openssl_dep.found()
|
||||
deps += openssl_dep
|
||||
args += '-DCPPHTTPLIB_OPENSSL_SUPPORT'
|
||||
if host_machine.system() == 'darwin'
|
||||
deps += dependency('appleframeworks', modules: ['CoreFoundation', 'Security'])
|
||||
macosx_keychain_dep = dependency('appleframeworks', modules: ['CoreFoundation', 'Security'], required: get_option('cpp-httplib_macosx_keychain'))
|
||||
if macosx_keychain_dep.found()
|
||||
deps += macosx_keychain_dep
|
||||
args += '-DCPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
option('cpp-httplib_openssl', type: 'feature', value: 'auto', description: 'Enable OpenSSL support')
|
||||
option('cpp-httplib_zlib', type: 'feature', value: 'auto', description: 'Enable zlib support')
|
||||
option('cpp-httplib_brotli', type: 'feature', value: 'auto', description: 'Enable Brotli support')
|
||||
option('cpp-httplib_macosx_keychain', type: 'feature', value: 'auto', description: 'Enable loading certs from the Keychain on Apple devices')
|
||||
option('cpp-httplib_compile', type: 'boolean', value: false, description: 'Split the header into a compilable header & source file (requires python3)')
|
||||
option('cpp-httplib_test', type: 'boolean', value: false, description: 'Build tests')
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPEN
|
||||
ifneq ($(OS), Windows_NT)
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S), Darwin)
|
||||
OPENSSL_SUPPORT += -framework CoreFoundation -framework Security
|
||||
OPENSSL_SUPPORT += -DCPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN -framework CoreFoundation -framework Security
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
+452
-289
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user