mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-07 07:34:19 +07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80c0cc445e | ||
|
|
762024b890 | ||
|
|
82a90a2325 | ||
|
|
b7cac4f4b8 | ||
|
|
e323374d2a | ||
|
|
ffc294d37e | ||
|
|
fceada9ef4 | ||
|
|
5f0f73fad9 | ||
|
|
530d6ee098 | ||
|
|
420c9759c6 | ||
|
|
2ce7c22218 | ||
|
|
4ef9ed80cd | ||
|
|
44b3fe6277 | ||
|
|
449801990f | ||
|
|
af2928d316 | ||
|
|
d948e38820 | ||
|
|
65218ce222 | ||
|
|
55e99c4030 | ||
|
|
b63d50671d | ||
|
|
eba980846b | ||
|
|
374d058de7 | ||
|
|
31cdcc3c3a | ||
|
|
ad9f6423e2 | ||
|
|
cbca63f091 | ||
|
|
b4748a226c | ||
|
|
5b943d9bb8 | ||
|
|
c86f69a105 | ||
|
|
d39fda0657 | ||
|
|
37f8dc4382 | ||
|
|
3a8adda381 | ||
|
|
8aa38aecaf | ||
|
|
f1dec77f46 | ||
|
|
cddaedaff8 | ||
|
|
cefb5a8822 | ||
|
|
e426a38c3e | ||
|
|
f14accb7b6 | ||
|
|
c5c704cb3b | ||
|
|
115a786581 | ||
|
|
5ef4cfd263 | ||
|
|
03fecb2f78 | ||
|
|
7fc8682a0a | ||
|
|
f1431311a4 | ||
|
|
1d14e051a5 | ||
|
|
97ae6733ed | ||
|
|
1d6b22b5f0 | ||
|
|
1a49076b5b | ||
|
|
d0e4cb3f07 | ||
|
|
e2813d9d4d | ||
|
|
20a7f088ce | ||
|
|
f63ba7d013 | ||
|
|
0a629d7391 | ||
|
|
a609330e4c | ||
|
|
c029597a5a |
+31
-39
@@ -3,11 +3,11 @@
|
|||||||
* BUILD_SHARED_LIBS (default off) builds as a shared library (if HTTPLIB_COMPILE is ON)
|
* BUILD_SHARED_LIBS (default off) builds as a shared library (if HTTPLIB_COMPILE is ON)
|
||||||
* HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on)
|
* HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on)
|
||||||
* HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on)
|
* HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on)
|
||||||
|
* HTTPLIB_USE_BROTLI_IF_AVAILABLE (default on)
|
||||||
* HTTPLIB_REQUIRE_OPENSSL (default off)
|
* HTTPLIB_REQUIRE_OPENSSL (default off)
|
||||||
* HTTPLIB_REQUIRE_ZLIB (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_REQUIRE_BROTLI (default off)
|
||||||
|
* HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on)
|
||||||
* HTTPLIB_COMPILE (default off)
|
* HTTPLIB_COMPILE (default off)
|
||||||
* HTTPLIB_INSTALL (default on)
|
* HTTPLIB_INSTALL (default on)
|
||||||
* HTTPLIB_TEST (default off)
|
* HTTPLIB_TEST (default off)
|
||||||
@@ -59,7 +59,6 @@
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
FindPython3 requires Cmake v3.12
|
|
||||||
ARCH_INDEPENDENT option of write_basic_package_version_file() requires Cmake v3.14
|
ARCH_INDEPENDENT option of write_basic_package_version_file() requires Cmake v3.14
|
||||||
]]
|
]]
|
||||||
cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)
|
||||||
@@ -69,20 +68,19 @@ cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)
|
|||||||
# This is so the maintainer doesn't actually need to update this manually.
|
# This is so the maintainer doesn't actually need to update this manually.
|
||||||
file(STRINGS httplib.h _raw_version_string REGEX "CPPHTTPLIB_VERSION \"([0-9]+\\.[0-9]+\\.[0-9]+)\"")
|
file(STRINGS httplib.h _raw_version_string REGEX "CPPHTTPLIB_VERSION \"([0-9]+\\.[0-9]+\\.[0-9]+)\"")
|
||||||
|
|
||||||
# Needed since git tags have "v" prefixing them.
|
# Extracts just the version string itself from the whole string contained in _raw_version_string
|
||||||
# Also used if the fallback to user agent string is being used.
|
# since _raw_version_string would contain the entire line of code where it found the version string
|
||||||
string(REGEX MATCH "([0-9]+\\.?)+" _httplib_version "${_raw_version_string}")
|
string(REGEX MATCH "([0-9]+\\.?)+" _httplib_version "${_raw_version_string}")
|
||||||
|
|
||||||
project(httplib VERSION ${_httplib_version} LANGUAGES CXX)
|
project(httplib VERSION ${_httplib_version} 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 "3.0.0")
|
||||||
|
|
||||||
# Lets you disable C++ exception during CMake configure time.
|
# Lets you disable C++ exception during CMake configure time.
|
||||||
# The value is used in the install CMake config file.
|
# The value is used in the install CMake config file.
|
||||||
option(HTTPLIB_NO_EXCEPTIONS "Disable the use of C++ exceptions" OFF)
|
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")
|
|
||||||
|
|
||||||
# Allow for a build to require OpenSSL to pass, instead of just being optional
|
# 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_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)
|
option(HTTPLIB_REQUIRE_ZLIB "Requires ZLIB to be found & linked, or fails build." OFF)
|
||||||
@@ -94,10 +92,6 @@ option(HTTPLIB_USE_ZLIB_IF_AVAILABLE "Uses ZLIB (if available) to enable Zlib co
|
|||||||
option(HTTPLIB_COMPILE "If ON, uses a Python script to split the header into a compilable header & source file (requires Python v3)." OFF)
|
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)
|
# Lets you disable the installation (useful when fetched from another CMake project)
|
||||||
option(HTTPLIB_INSTALL "Enables the installation target" ON)
|
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)
|
|
||||||
endif()
|
|
||||||
option(HTTPLIB_TEST "Enables testing and builds tests" OFF)
|
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_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_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON)
|
||||||
@@ -110,45 +104,48 @@ if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
|
|||||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Set some variables that are used in-tree and while building based on our options
|
||||||
|
set(HTTPLIB_IS_COMPILED ${HTTPLIB_COMPILE})
|
||||||
|
set(HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN ${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN})
|
||||||
|
|
||||||
# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
|
# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG true)
|
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
# Since Cmake v3.11, Crypto & SSL became optional when not specified as COMPONENTS.
|
# Since Cmake v3.11, Crypto & SSL became optional when not specified as COMPONENTS.
|
||||||
if(HTTPLIB_REQUIRE_OPENSSL)
|
if(HTTPLIB_REQUIRE_OPENSSL)
|
||||||
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL REQUIRED)
|
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL REQUIRED)
|
||||||
|
set(HTTPLIB_IS_USING_OPENSSL TRUE)
|
||||||
elseif(HTTPLIB_USE_OPENSSL_IF_AVAILABLE)
|
elseif(HTTPLIB_USE_OPENSSL_IF_AVAILABLE)
|
||||||
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL QUIET)
|
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL QUIET)
|
||||||
endif()
|
# Avoid a rare circumstance of not finding all components but the end-user did their
|
||||||
# Just setting this variable here for people building in-tree
|
# own call for OpenSSL, which might trick us into thinking we'd otherwise have what we wanted
|
||||||
if(OPENSSL_FOUND AND NOT DEFINED HTTPLIB_IS_USING_OPENSSL)
|
if (TARGET OpenSSL::SSL AND TARGET OpenSSL::Crypto)
|
||||||
set(HTTPLIB_IS_USING_OPENSSL TRUE)
|
set(HTTPLIB_IS_USING_OPENSSL ${OPENSSL_FOUND})
|
||||||
|
else()
|
||||||
|
set(HTTPLIB_IS_USING_OPENSSL FALSE)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(HTTPLIB_REQUIRE_ZLIB)
|
if(HTTPLIB_REQUIRE_ZLIB)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
|
set(HTTPLIB_IS_USING_ZLIB TRUE)
|
||||||
elseif(HTTPLIB_USE_ZLIB_IF_AVAILABLE)
|
elseif(HTTPLIB_USE_ZLIB_IF_AVAILABLE)
|
||||||
find_package(ZLIB QUIET)
|
find_package(ZLIB QUIET)
|
||||||
endif()
|
# FindZLIB doesn't have a ZLIB_FOUND variable, so check the target.
|
||||||
# Just setting this variable here for people building in-tree
|
if(TARGET ZLIB::ZLIB)
|
||||||
# FindZLIB doesn't have a ZLIB_FOUND variable, so check the target.
|
set(HTTPLIB_IS_USING_ZLIB TRUE)
|
||||||
if(TARGET ZLIB::ZLIB)
|
endif()
|
||||||
set(HTTPLIB_IS_USING_ZLIB TRUE)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Adds our cmake folder to the search path for find_package
|
# Adds our cmake folder to the search path for find_package
|
||||||
|
# This is so we can use our custom FindBrotli.cmake
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
if(HTTPLIB_REQUIRE_BROTLI)
|
if(HTTPLIB_REQUIRE_BROTLI)
|
||||||
find_package(Brotli COMPONENTS encoder decoder common REQUIRED)
|
find_package(Brotli COMPONENTS encoder decoder common REQUIRED)
|
||||||
|
set(HTTPLIB_IS_USING_BROTLI TRUE)
|
||||||
elseif(HTTPLIB_USE_BROTLI_IF_AVAILABLE)
|
elseif(HTTPLIB_USE_BROTLI_IF_AVAILABLE)
|
||||||
find_package(Brotli COMPONENTS encoder decoder common QUIET)
|
find_package(Brotli COMPONENTS encoder decoder common QUIET)
|
||||||
endif()
|
set(HTTPLIB_IS_USING_BROTLI ${Brotli_FOUND})
|
||||||
# Just setting this variable here for people building in-tree
|
|
||||||
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()
|
endif()
|
||||||
|
|
||||||
# Used for default, common dirs that the end-user can change (if needed)
|
# Used for default, common dirs that the end-user can change (if needed)
|
||||||
@@ -204,9 +201,7 @@ endif()
|
|||||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||||
|
|
||||||
# Require C++11
|
# Require C++11
|
||||||
target_compile_features(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
target_compile_features(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC} cxx_std_11)
|
||||||
cxx_std_11
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} SYSTEM ${_INTERFACE_OR_PUBLIC}
|
target_include_directories(${PROJECT_NAME} SYSTEM ${_INTERFACE_OR_PUBLIC}
|
||||||
$<BUILD_INTERFACE:${_httplib_build_includedir}>
|
$<BUILD_INTERFACE:${_httplib_build_includedir}>
|
||||||
@@ -219,7 +214,6 @@ target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
|||||||
# Needed for Windows libs on Mingw, as the pragma comment(lib, "xyz") aren't triggered.
|
# Needed for Windows libs on Mingw, as the pragma comment(lib, "xyz") aren't triggered.
|
||||||
$<$<PLATFORM_ID:Windows>:ws2_32>
|
$<$<PLATFORM_ID:Windows>:ws2_32>
|
||||||
$<$<PLATFORM_ID:Windows>:crypt32>
|
$<$<PLATFORM_ID:Windows>:crypt32>
|
||||||
$<$<PLATFORM_ID:Windows>:cryptui>
|
|
||||||
# Needed for API from MacOS Security framework
|
# Needed for API from MacOS Security framework
|
||||||
"$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN}>>:-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.
|
# Can't put multiple targets in a single generator expression or it bugs out.
|
||||||
@@ -274,9 +268,7 @@ if(HTTPLIB_INSTALL)
|
|||||||
# Creates the export httplibTargets.cmake
|
# Creates the export httplibTargets.cmake
|
||||||
# This is strictly what holds compilation requirements
|
# This is strictly what holds compilation requirements
|
||||||
# and linkage information (doesn't find deps though).
|
# and linkage information (doesn't find deps though).
|
||||||
install(TARGETS ${PROJECT_NAME}
|
install(TARGETS ${PROJECT_NAME} EXPORT httplibTargets)
|
||||||
EXPORT httplibTargets
|
|
||||||
)
|
|
||||||
|
|
||||||
install(FILES "${_httplib_build_includedir}/httplib.h" TYPE INCLUDE)
|
install(FILES "${_httplib_build_includedir}/httplib.h" TYPE INCLUDE)
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ SSL Support
|
|||||||
|
|
||||||
SSL support is available with `CPPHTTPLIB_OPENSSL_SUPPORT`. `libssl` and `libcrypto` should be linked.
|
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: cpp-httplib currently supports only version 3.0 or later. Please see [this page](https://www.openssl.org/policies/releasestrat.html) to get more information.
|
||||||
|
|
||||||
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`.
|
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`.
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ svr.set_exception_handler([](const auto& req, auto& res, std::exception_ptr ep)
|
|||||||
snprintf(buf, sizeof(buf), fmt, "Unknown Exception");
|
snprintf(buf, sizeof(buf), fmt, "Unknown Exception");
|
||||||
}
|
}
|
||||||
res.set_content(buf, "text/html");
|
res.set_content(buf, "text/html");
|
||||||
res.status = 500;
|
res.status = StatusCode::InternalServerError_500;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -385,14 +385,14 @@ By default, the server sends a `100 Continue` response for an `Expect: 100-conti
|
|||||||
```cpp
|
```cpp
|
||||||
// Send a '417 Expectation Failed' response.
|
// Send a '417 Expectation Failed' response.
|
||||||
svr.set_expect_100_continue_handler([](const Request &req, Response &res) {
|
svr.set_expect_100_continue_handler([](const Request &req, Response &res) {
|
||||||
return 417;
|
return StatusCode::ExpectationFailed_417;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// Send a final status without reading the message body.
|
// Send a final status without reading the message body.
|
||||||
svr.set_expect_100_continue_handler([](const Request &req, Response &res) {
|
svr.set_expect_100_continue_handler([](const Request &req, Response &res) {
|
||||||
return res.status = 401;
|
return res.status = StatusCode::Unauthorized_401;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -417,6 +417,8 @@ svr.set_idle_interval(0, 100000); // 100 milliseconds
|
|||||||
svr.set_payload_max_length(1024 * 1024 * 512); // 512MB
|
svr.set_payload_max_length(1024 * 1024 * 512); // 512MB
|
||||||
```
|
```
|
||||||
|
|
||||||
|
NOTE: When the request body content type is 'www-form-urlencoded', the actual payload length shouldn't exceed `CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH`.
|
||||||
|
|
||||||
### Server-Sent Events
|
### Server-Sent Events
|
||||||
|
|
||||||
Please see [Server example](https://github.com/yhirose/cpp-httplib/blob/master/example/ssesvr.cc) and [Client example](https://github.com/yhirose/cpp-httplib/blob/master/example/ssecli.cc).
|
Please see [Server example](https://github.com/yhirose/cpp-httplib/blob/master/example/ssesvr.cc) and [Client example](https://github.com/yhirose/cpp-httplib/blob/master/example/ssecli.cc).
|
||||||
@@ -431,6 +433,17 @@ If you want to set the thread count at runtime, there is no convenient way... Bu
|
|||||||
svr.new_task_queue = [] { return new ThreadPool(12); };
|
svr.new_task_queue = [] { return new ThreadPool(12); };
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can also provide an optional parameter to limit the maximum number
|
||||||
|
of pending requests, i.e. requests `accept()`ed by the listener but
|
||||||
|
still waiting to be serviced by worker threads.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
svr.new_task_queue = [] { return new ThreadPool(/*num_threads=*/12, /*max_queued_requests=*/18); };
|
||||||
|
```
|
||||||
|
|
||||||
|
Default limit is 0 (unlimited). Once the limit is reached, the listener
|
||||||
|
will shutdown the client connection.
|
||||||
|
|
||||||
### Override the default thread pool with yours
|
### Override the default thread pool with yours
|
||||||
|
|
||||||
You can supply your own thread pool implementation according to your need.
|
You can supply your own thread pool implementation according to your need.
|
||||||
@@ -442,8 +455,10 @@ public:
|
|||||||
pool_.start_with_thread_count(n);
|
pool_.start_with_thread_count(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void enqueue(std::function<void()> fn) override {
|
virtual bool enqueue(std::function<void()> fn) override {
|
||||||
pool_.enqueue(fn);
|
/* Return true if the task was actually enqueued, or false
|
||||||
|
* if the caller must drop the corresponding connection. */
|
||||||
|
return pool_.enqueue(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void shutdown() override {
|
virtual void shutdown() override {
|
||||||
@@ -471,7 +486,7 @@ int main(void)
|
|||||||
httplib::Client cli("localhost", 1234);
|
httplib::Client cli("localhost", 1234);
|
||||||
|
|
||||||
if (auto res = cli.Get("/hi")) {
|
if (auto res = cli.Get("/hi")) {
|
||||||
if (res->status == 200) {
|
if (res->status == StatusCode::OK_200) {
|
||||||
std::cout << res->body << std::endl;
|
std::cout << res->body << std::endl;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -621,7 +636,7 @@ std::string body;
|
|||||||
auto res = cli.Get(
|
auto res = cli.Get(
|
||||||
"/stream", Headers(),
|
"/stream", Headers(),
|
||||||
[&](const Response &response) {
|
[&](const Response &response) {
|
||||||
EXPECT_EQ(200, response.status);
|
EXPECT_EQ(StatusCode::OK_200, response.status);
|
||||||
return true; // return 'false' if you want to cancel the request.
|
return true; // return 'false' if you want to cancel the request.
|
||||||
},
|
},
|
||||||
[&](const char *data, size_t data_length) {
|
[&](const char *data, size_t data_length) {
|
||||||
@@ -662,7 +677,7 @@ auto res = cli.Post(
|
|||||||
### With Progress Callback
|
### With Progress Callback
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
httplib::Client client(url, port);
|
httplib::Client cli(url, port);
|
||||||
|
|
||||||
// prints: 0 / 000 bytes => 50% complete
|
// prints: 0 / 000 bytes => 50% complete
|
||||||
auto res = cli.Get("/", [](uint64_t len, uint64_t total) {
|
auto res = cli.Get("/", [](uint64_t len, uint64_t total) {
|
||||||
@@ -846,12 +861,12 @@ Include `httplib.h` before `Windows.h` or include `Windows.h` by defining `WIN32
|
|||||||
|
|
||||||
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 and MSYS2 including MinGW are neither supported nor tested.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
MIT license (© 2023 Yuji Hirose)
|
MIT license (© 2024 Yuji Hirose)
|
||||||
|
|
||||||
Special Thanks To
|
Special Thanks To
|
||||||
-----------------
|
-----------------
|
||||||
|
|||||||
+1
-2
@@ -4,8 +4,7 @@ CXXFLAGS = -O2 -std=c++11 -I.. -Wall -Wextra -pthread
|
|||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
#PREFIX = $(shell brew --prefix)
|
#PREFIX = $(shell brew --prefix)
|
||||||
|
|
||||||
OPENSSL_DIR = $(PREFIX)/opt/openssl@1.1
|
OPENSSL_DIR = $(PREFIX)/opt/openssl@3
|
||||||
#OPENSSL_DIR = $(PREFIX)/opt/openssl@3
|
|
||||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
|
|
||||||
ifneq ($(OS), Windows_NT)
|
ifneq ($(OS), Windows_NT)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ int main(void) {
|
|||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
StopWatch sw(to_string(i).c_str());
|
StopWatch sw(to_string(i).c_str());
|
||||||
auto res = cli.Post("/post", body, "application/octet-stream");
|
auto res = cli.Post("/post", body, "application/octet-stream");
|
||||||
assert(res->status == 200);
|
assert(res->status == httplib::StatusCode::OK_200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ endif
|
|||||||
deps = [dependency('threads')]
|
deps = [dependency('threads')]
|
||||||
args = []
|
args = []
|
||||||
|
|
||||||
openssl_dep = dependency('openssl', version: '>=1.1.1', required: get_option('cpp-httplib_openssl'))
|
openssl_dep = dependency('openssl', version: '>=3.0.0', required: get_option('cpp-httplib_openssl'))
|
||||||
if openssl_dep.found()
|
if openssl_dep.found()
|
||||||
deps += openssl_dep
|
deps += openssl_dep
|
||||||
args += '-DCPPHTTPLIB_OPENSSL_SUPPORT'
|
args += '-DCPPHTTPLIB_OPENSSL_SUPPORT'
|
||||||
|
|||||||
@@ -102,3 +102,5 @@ if(HTTPLIB_IS_USING_OPENSSL)
|
|||||||
COMMAND_ERROR_IS_FATAL ANY
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(fuzzing)
|
||||||
|
|||||||
+1
-2
@@ -4,8 +4,7 @@ CXXFLAGS = -g -std=c++11 -I. -Wall -Wextra -Wtype-limits -Wconversion -Wshadow #
|
|||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
#PREFIX = $(shell brew --prefix)
|
#PREFIX = $(shell brew --prefix)
|
||||||
|
|
||||||
OPENSSL_DIR = $(PREFIX)/opt/openssl@1.1
|
OPENSSL_DIR = $(PREFIX)/opt/openssl@3
|
||||||
#OPENSSL_DIR = $(PREFIX)/opt/openssl@3
|
|
||||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
|
|
||||||
ifneq ($(OS), Windows_NT)
|
ifneq ($(OS), Windows_NT)
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
file(GLOB HTTPLIB_CORPUS corpus/*)
|
||||||
|
add_executable(httplib-test-fuzz
|
||||||
|
server_fuzzer.cc
|
||||||
|
standalone_fuzz_target_runner.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(httplib-test-fuzz PRIVATE httplib)
|
||||||
|
add_test(
|
||||||
|
NAME httplib-test-fuzz
|
||||||
|
COMMAND httplib-test-fuzz ${HTTPLIB_CORPUS}
|
||||||
|
)
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include <httplib.h>
|
#include <httplib.h>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class FuzzedStream : public httplib::Stream {
|
class FuzzedStream : public httplib::Stream {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
// on the test corpus or on a single file,
|
// on the test corpus or on a single file,
|
||||||
// e.g. the one that comes from a bug report.
|
// e.g. the one that comes from a bug report.
|
||||||
|
|
||||||
#include <cassert>
|
#include <cstdint>
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// Forward declare the "fuzz target" interface.
|
// Forward declare the "fuzz target" interface.
|
||||||
@@ -21,7 +21,7 @@ int main(int argc, char **argv) {
|
|||||||
std::ifstream in(argv[i]);
|
std::ifstream in(argv[i]);
|
||||||
in.seekg(0, in.end);
|
in.seekg(0, in.end);
|
||||||
size_t length = static_cast<size_t>(in.tellg());
|
size_t length = static_cast<size_t>(in.tellg());
|
||||||
in.seekg (0, in.beg);
|
in.seekg(0, in.beg);
|
||||||
std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl;
|
std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl;
|
||||||
// Allocate exactly length bytes so that we reliably catch buffer overflows.
|
// Allocate exactly length bytes so that we reliably catch buffer overflows.
|
||||||
std::vector<char> bytes(length);
|
std::vector<char> bytes(length);
|
||||||
|
|||||||
+617
-377
File diff suppressed because it is too large
Load Diff
+15
-15
@@ -10,7 +10,7 @@ void ProxyTest(T& cli, bool basic) {
|
|||||||
cli.set_proxy("localhost", basic ? 3128 : 3129);
|
cli.set_proxy("localhost", basic ? 3128 : 3129);
|
||||||
auto res = cli.Get("/httpbin/get");
|
auto res = cli.Get("/httpbin/get");
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(407, res->status);
|
EXPECT_EQ(StatusCode::ProxyAuthenticationRequired_407, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ProxyTest, NoSSLBasic) {
|
TEST(ProxyTest, NoSSLBasic) {
|
||||||
@@ -51,7 +51,7 @@ void RedirectProxyText(T& cli, const char *path, bool basic) {
|
|||||||
|
|
||||||
auto res = cli.Get(path);
|
auto res = cli.Get(path);
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RedirectTest, HTTPBinNoSSLBasic) {
|
TEST(RedirectTest, HTTPBinNoSSLBasic) {
|
||||||
@@ -108,7 +108,7 @@ void BaseAuthTestFromHTTPWatch(T& cli) {
|
|||||||
{
|
{
|
||||||
auto res = cli.Get("/basic-auth/hello/world");
|
auto res = cli.Get("/basic-auth/hello/world");
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(401, res->status);
|
EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -117,7 +117,7 @@ void BaseAuthTestFromHTTPWatch(T& cli) {
|
|||||||
{make_basic_authentication_header("hello", "world")});
|
{make_basic_authentication_header("hello", "world")});
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -125,21 +125,21 @@ void BaseAuthTestFromHTTPWatch(T& cli) {
|
|||||||
auto res = cli.Get("/basic-auth/hello/world");
|
auto res = cli.Get("/basic-auth/hello/world");
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
cli.set_basic_auth("hello", "bad");
|
cli.set_basic_auth("hello", "bad");
|
||||||
auto res = cli.Get("/basic-auth/hello/world");
|
auto res = cli.Get("/basic-auth/hello/world");
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(401, res->status);
|
EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
cli.set_basic_auth("bad", "world");
|
cli.set_basic_auth("bad", "world");
|
||||||
auto res = cli.Get("/basic-auth/hello/world");
|
auto res = cli.Get("/basic-auth/hello/world");
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(401, res->status);
|
EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ void DigestAuthTestFromHTTPWatch(T& cli) {
|
|||||||
{
|
{
|
||||||
auto res = cli.Get("/digest-auth/auth/hello/world");
|
auto res = cli.Get("/digest-auth/auth/hello/world");
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(401, res->status);
|
EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -182,14 +182,14 @@ void DigestAuthTestFromHTTPWatch(T& cli) {
|
|||||||
auto res = cli.Get(path.c_str());
|
auto res = cli.Get(path.c_str());
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
cli.set_digest_auth("hello", "bad");
|
cli.set_digest_auth("hello", "bad");
|
||||||
for (auto path : paths) {
|
for (auto path : paths) {
|
||||||
auto res = cli.Get(path.c_str());
|
auto res = cli.Get(path.c_str());
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(401, res->status);
|
EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Until httpbin.org fixes issue #46, the following test is commented
|
// NOTE: Until httpbin.org fixes issue #46, the following test is commented
|
||||||
@@ -198,7 +198,7 @@ void DigestAuthTestFromHTTPWatch(T& cli) {
|
|||||||
// for (auto path : paths) {
|
// for (auto path : paths) {
|
||||||
// auto res = cli.Get(path.c_str());
|
// auto res = cli.Get(path.c_str());
|
||||||
// ASSERT_TRUE(res != nullptr);
|
// ASSERT_TRUE(res != nullptr);
|
||||||
// EXPECT_EQ(401, res->status);
|
// EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,11 +234,11 @@ void KeepAliveTest(T& cli, bool basic) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
auto res = cli.Get("/httpbin/get");
|
auto res = cli.Get("/httpbin/get");
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto res = cli.Get("/httpbin/redirect/2");
|
auto res = cli.Get("/httpbin/redirect/2");
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -252,7 +252,7 @@ void KeepAliveTest(T& cli, bool basic) {
|
|||||||
for (auto path: paths) {
|
for (auto path: paths) {
|
||||||
auto res = cli.Get(path.c_str());
|
auto res = cli.Get(path.c_str());
|
||||||
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ void KeepAliveTest(T& cli, bool basic) {
|
|||||||
int count = 10;
|
int count = 10;
|
||||||
while (count--) {
|
while (count--) {
|
||||||
auto res = cli.Get("/httpbin/get");
|
auto res = cli.Get("/httpbin/get");
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,3 +5,4 @@
|
|||||||
configure_file(input: 'index.html', output: 'index.html', copy: true)
|
configure_file(input: 'index.html', output: 'index.html', copy: true)
|
||||||
configure_file(input: 'test.abcde', output: 'test.abcde', copy: true)
|
configure_file(input: 'test.abcde', output: 'test.abcde', copy: true)
|
||||||
configure_file(input: 'test.html', output: 'test.html', copy: true)
|
configure_file(input: 'test.html', output: 'test.html', copy: true)
|
||||||
|
configure_file(input: '1MB.txt', output: '1MB.txt', copy: true)
|
||||||
|
|||||||
Reference in New Issue
Block a user