mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-08 16:04:46 +07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c00bbf36b | ||
|
|
9d6f5372a3 | ||
|
|
f06fd934f6 | ||
|
|
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 | ||
|
|
30b7732565 | ||
|
|
6650632e7f | ||
|
|
afe627e7af | ||
|
|
67f6ff7fa9 | ||
|
|
c7ed1796a7 | ||
|
|
44c62d838e | ||
|
|
6bb580cda8 | ||
|
|
00a8cb8e5d | ||
|
|
2e34a39673 | ||
|
|
01b90829bc | ||
|
|
e699bd0730 | ||
|
|
961a9379d5 | ||
|
|
ec87b04aff | ||
|
|
aabf752a51 | ||
|
|
afb0674ccb | ||
|
|
ee625232a4 | ||
|
|
52d8dd41f1 | ||
|
|
be07d2d7a9 | ||
|
|
0f1b62c2b3 | ||
|
|
c30906a541 | ||
|
|
3533503323 | ||
|
|
82acdca638 | ||
|
|
a1e56a567b | ||
|
|
0c17d172a2 | ||
|
|
5d8e7c761f | ||
|
|
17fc522b75 | ||
|
|
f1daa5b88b | ||
|
|
fe9a1949a6 | ||
|
|
50cba6db9f | ||
|
|
18592e7f98 | ||
|
|
bd9612b81e | ||
|
|
7ab5fb65b2 | ||
|
|
8df5fedc35 | ||
|
|
4a61f68fa4 | ||
|
|
067890133c | ||
|
|
d3076f5a70 | ||
|
|
ed129f057f | ||
|
|
eab5ea01d7 | ||
|
|
3e287b3a26 | ||
|
|
4f33637b43 | ||
|
|
698a1e51ec | ||
|
|
27c0e1186c | ||
|
|
c54c71a3e5 | ||
|
|
3409c00e6f | ||
|
|
f8ef5fab64 | ||
|
|
5b397d455d | ||
|
|
f977558a28 | ||
|
|
c2e156e0e0 | ||
|
|
7aba2938d3 | ||
|
|
d587548250 | ||
|
|
21f9c51556 | ||
|
|
985ceba525 | ||
|
|
e62a4b02e5 | ||
|
|
ff34749572 | ||
|
|
e5804d4a50 | ||
|
|
3956a2b790 | ||
|
|
b33aa52dc2 | ||
|
|
76230db97f | ||
|
|
a66a013ed7 | ||
|
|
f4b02dfdc1 | ||
|
|
4cf218643e | ||
|
|
8f96b69a25 | ||
|
|
d262033ded | ||
|
|
5745eabe69 | ||
|
|
5f18642271 | ||
|
|
88a9278872 | ||
|
|
9bb3ca8169 |
@@ -17,7 +17,7 @@ jobs:
|
|||||||
git config --global core.autocrlf false
|
git config --global core.autocrlf false
|
||||||
git config --global core.eol lf
|
git config --global core.eol lf
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: install brotli library on ubuntu
|
- name: install brotli library on ubuntu
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
run: sudo apt update && sudo apt-get install -y libbrotli-dev
|
run: sudo apt update && sudo apt-get install -y libbrotli-dev
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
run: cd test && make fuzz_test
|
run: cd test && make fuzz_test
|
||||||
- name: setup msbuild on windows
|
- name: setup msbuild on windows
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
uses: microsoft/setup-msbuild@v1.0.2
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
- name: make-windows
|
- name: make-windows
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
+57
-47
@@ -3,11 +3,13 @@
|
|||||||
* 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_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_TEST (default off)
|
* HTTPLIB_TEST (default off)
|
||||||
* BROTLI_USE_STATIC_LIBS - tells Cmake to use the static Brotli libs (only works if you have them installed).
|
* 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).
|
* 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_OPENSSL - a bool for if OpenSSL support is enabled.
|
||||||
* HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB 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_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_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_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).
|
* HTTPLIB_LIBRARY - the full path to the library if compiled (e.g. /usr/lib/libhttplib.so).
|
||||||
@@ -56,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)
|
||||||
@@ -66,16 +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.
|
# Change as needed to set an OpenSSL minimum version.
|
||||||
# This is used in the installed Cmake config file.
|
# This is used in the installed Cmake config file.
|
||||||
set(_HTTPLIB_OPENSSL_MIN_VER "1.1.1")
|
set(_HTTPLIB_OPENSSL_MIN_VER "3.0.0")
|
||||||
|
|
||||||
|
# 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)
|
||||||
# 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)
|
||||||
@@ -85,13 +90,12 @@ 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)
|
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
|
# 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)
|
option(HTTPLIB_COMPILE "If ON, uses a Python script to split the header into a compilable header & source file (requires Python v3)." OFF)
|
||||||
# Just setting this variable here for people building in-tree
|
# Lets you disable the installation (useful when fetched from another CMake project)
|
||||||
if(HTTPLIB_COMPILE)
|
option(HTTPLIB_INSTALL "Enables the installation target" ON)
|
||||||
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)
|
||||||
|
option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system certs from the Apple Keychain." ON)
|
||||||
# Defaults to static library
|
# 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)
|
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)
|
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
|
||||||
@@ -100,41 +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)
|
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()
|
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)
|
||||||
@@ -190,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}>
|
||||||
@@ -205,9 +214,8 @@ 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}>>:-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.
|
||||||
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::common>
|
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::common>
|
||||||
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::encoder>
|
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::encoder>
|
||||||
@@ -219,9 +227,11 @@ target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
|||||||
|
|
||||||
# Set the definitions to enable optional features
|
# Set the definitions to enable optional features
|
||||||
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
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_BROTLI}>:CPPHTTPLIB_BROTLI_SUPPORT>
|
||||||
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
|
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
|
||||||
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_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
|
# CMake configuration files installation directory
|
||||||
@@ -240,13 +250,13 @@ configure_package_config_file("${PROJECT_NAME}Config.cmake.in"
|
|||||||
if(HTTPLIB_COMPILE)
|
if(HTTPLIB_COMPILE)
|
||||||
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
||||||
# Example: if you find_package(httplib 0.5.4)
|
# Example: if you find_package(httplib 0.5.4)
|
||||||
# then anything >= 0.5 and <= 1.0 is accepted
|
# then anything >= 0.5.4 and < 0.6 is accepted
|
||||||
COMPATIBILITY SameMinorVersion
|
COMPATIBILITY SameMinorVersion
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
||||||
# Example: if you find_package(httplib 0.5.4)
|
# Example: if you find_package(httplib 0.5.4)
|
||||||
# then anything >= 0.5 and <= 1.0 is accepted
|
# then anything >= 0.5.4 and < 0.6 is accepted
|
||||||
COMPATIBILITY SameMinorVersion
|
COMPATIBILITY SameMinorVersion
|
||||||
# Tells Cmake that it's a header-only lib
|
# Tells Cmake that it's a header-only lib
|
||||||
# Mildly useful for end-users :)
|
# Mildly useful for end-users :)
|
||||||
@@ -254,31 +264,31 @@ else()
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Creates the export httplibTargets.cmake
|
if(HTTPLIB_INSTALL)
|
||||||
# This is strictly what holds compilation requirements
|
# Creates the export httplibTargets.cmake
|
||||||
# and linkage information (doesn't find deps though).
|
# This is strictly what holds compilation requirements
|
||||||
install(TARGETS ${PROJECT_NAME}
|
# and linkage information (doesn't find deps though).
|
||||||
EXPORT httplibTargets
|
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}Config.cmake"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||||
# Install it so it can be used later by the httplibConfig.cmake file.
|
# 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.
|
# 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"
|
"${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
|
# NOTE: This path changes depending on if it's on Windows or Linux
|
||||||
install(EXPORT httplibTargets
|
install(EXPORT httplibTargets
|
||||||
# Puts the targets into the httplib namespace
|
# Puts the targets into the httplib namespace
|
||||||
# So this makes httplib::httplib linkable after doing find_package(httplib)
|
# So this makes httplib::httplib linkable after doing find_package(httplib)
|
||||||
NAMESPACE ${PROJECT_NAME}::
|
NAMESPACE ${PROJECT_NAME}::
|
||||||
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
|
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(HTTPLIB_TEST)
|
if(HTTPLIB_TEST)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|||||||
@@ -53,8 +53,9 @@ 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 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++
|
```c++
|
||||||
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
@@ -75,7 +76,7 @@ cli.set_ca_cert_path("./ca-bundle.crt");
|
|||||||
cli.enable_server_certificate_verification(false);
|
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
|
Server
|
||||||
------
|
------
|
||||||
@@ -93,11 +94,20 @@ int main(void)
|
|||||||
res.set_content("Hello World!", "text/plain");
|
res.set_content("Hello World!", "text/plain");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Match the request path against a regular expression
|
||||||
|
// and extract its captures
|
||||||
svr.Get(R"(/numbers/(\d+))", [&](const Request& req, Response& res) {
|
svr.Get(R"(/numbers/(\d+))", [&](const Request& req, Response& res) {
|
||||||
auto numbers = req.matches[1];
|
auto numbers = req.matches[1];
|
||||||
res.set_content(numbers, "text/plain");
|
res.set_content(numbers, "text/plain");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Capture the second segment of the request path as "id" path param
|
||||||
|
svr.Get("/users/:id", [&](const Request& req, Response& res) {
|
||||||
|
auto user_id = req.path_params.at("id");
|
||||||
|
res.set_content(user_id, "text/plain");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extract values from HTTP headers and URL query params
|
||||||
svr.Get("/body-header-param", [](const Request& req, Response& res) {
|
svr.Get("/body-header-param", [](const Request& req, Response& res) {
|
||||||
if (req.has_header("Content-Length")) {
|
if (req.has_header("Content-Length")) {
|
||||||
auto val = req.get_header_value("Content-Length");
|
auto val = req.get_header_value("Content-Length");
|
||||||
@@ -180,6 +190,8 @@ The followings are built-in mappings:
|
|||||||
| webm | video/webm | zip | application/zip |
|
| webm | video/webm | zip | application/zip |
|
||||||
| mp3 | audio/mp3 | wasm | application/wasm |
|
| mp3 | audio/mp3 | wasm | application/wasm |
|
||||||
|
|
||||||
|
NOTE: These static file server methods are not thread-safe.
|
||||||
|
|
||||||
### File request handler
|
### File request handler
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
@@ -189,8 +201,6 @@ svr.set_file_request_handler([](const Request &req, Response &res) {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: These static file server methods are not thread-safe.
|
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
@@ -225,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;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -302,7 +312,7 @@ svr.Get("/stream", [&](const Request &req, Response &res) {
|
|||||||
res.set_content_provider(
|
res.set_content_provider(
|
||||||
data->size(), // Content length
|
data->size(), // Content length
|
||||||
"text/plain", // Content type
|
"text/plain", // Content type
|
||||||
[data](size_t offset, size_t length, DataSink &sink) {
|
[&, data](size_t offset, size_t length, DataSink &sink) {
|
||||||
const auto &d = *data;
|
const auto &d = *data;
|
||||||
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
|
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
|
||||||
return true; // return 'false' if you want to cancel the process.
|
return true; // return 'false' if you want to cancel the process.
|
||||||
@@ -347,6 +357,27 @@ svr.Get("/chunked", [&](const Request& req, Response& res) {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
With trailer:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
svr.Get("/chunked", [&](const Request& req, Response& res) {
|
||||||
|
res.set_header("Trailer", "Dummy1, Dummy2");
|
||||||
|
res.set_chunked_content_provider(
|
||||||
|
"text/plain",
|
||||||
|
[](size_t offset, DataSink &sink) {
|
||||||
|
sink.write("123", 3);
|
||||||
|
sink.write("345", 3);
|
||||||
|
sink.write("789", 3);
|
||||||
|
sink.done_with_trailer({
|
||||||
|
{"Dummy1", "DummyVal1"},
|
||||||
|
{"Dummy2", "DummyVal2"}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
### 'Expect: 100-continue' handler
|
### 'Expect: 100-continue' handler
|
||||||
|
|
||||||
By default, the server sends a `100 Continue` response for an `Expect: 100-continue` header.
|
By default, the server sends a `100 Continue` response for an `Expect: 100-continue` header.
|
||||||
@@ -354,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;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -386,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).
|
||||||
@@ -400,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.
|
||||||
@@ -411,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 {
|
||||||
@@ -440,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 {
|
||||||
@@ -590,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) {
|
||||||
@@ -631,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) {
|
||||||
@@ -813,14 +859,14 @@ Include `httplib.h` before `Windows.h` or include `Windows.h` by defining `WIN32
|
|||||||
#include <httplib.h>
|
#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 and MSYS2 including MinGW are neither supported nor tested.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
MIT license (© 2022 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;
|
||||||
|
|||||||
+6
-2
@@ -30,12 +30,16 @@ 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'
|
||||||
if host_machine.system() == 'darwin'
|
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
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,6 @@
|
|||||||
option('cpp-httplib_openssl', type: 'feature', value: 'auto', description: 'Enable OpenSSL support')
|
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_zlib', type: 'feature', value: 'auto', description: 'Enable zlib support')
|
||||||
option('cpp-httplib_brotli', type: 'feature', value: 'auto', description: 'Enable Brotli 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_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')
|
option('cpp-httplib_test', type: 'boolean', value: false, description: 'Build tests')
|
||||||
|
|||||||
@@ -102,3 +102,5 @@ if(HTTPLIB_IS_USING_OPENSSL)
|
|||||||
COMMAND_ERROR_IS_FATAL ANY
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(fuzzing)
|
||||||
|
|||||||
+2
-3
@@ -4,14 +4,13 @@ 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)
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
ifeq ($(UNAME_S), Darwin)
|
ifeq ($(UNAME_S), Darwin)
|
||||||
OPENSSL_SUPPORT += -framework CoreFoundation -framework Security
|
OPENSSL_SUPPORT += -DCPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN -framework CoreFoundation -framework Security
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -1912,7 +1912,7 @@ void AssertHelper::operator=(const Message& message) const {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// When TEST_P is found without a matching INSTANTIATE_TEST_SUITE_P
|
// When TEST_P is found without a matching INSTANTIATE_TEST_SUITE_P
|
||||||
// to creates test cases for it, a syntetic test case is
|
// to creates test cases for it, a synthetic test case is
|
||||||
// inserted to report ether an error or a log message.
|
// inserted to report ether an error or a log message.
|
||||||
//
|
//
|
||||||
// This configuration bit will likely be removed at some point.
|
// This configuration bit will likely be removed at some point.
|
||||||
|
|||||||
+8
-1
@@ -86,6 +86,12 @@ subdir(join_paths('www', 'dir'))
|
|||||||
subdir(join_paths('www2', 'dir'))
|
subdir(join_paths('www2', 'dir'))
|
||||||
subdir(join_paths('www3', 'dir'))
|
subdir(join_paths('www3', 'dir'))
|
||||||
|
|
||||||
|
# GoogleTest 1.13.0 requires C++14
|
||||||
|
test_options = []
|
||||||
|
if gtest_dep.version().version_compare('>=1.13.0')
|
||||||
|
test_options += 'cpp_std=c++14'
|
||||||
|
endif
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'main',
|
'main',
|
||||||
executable(
|
executable(
|
||||||
@@ -94,7 +100,8 @@ test(
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
cpp_httplib_dep,
|
cpp_httplib_dep,
|
||||||
gtest_dep
|
gtest_dep
|
||||||
]
|
],
|
||||||
|
override_options: test_options
|
||||||
),
|
),
|
||||||
depends: [
|
depends: [
|
||||||
key_pem,
|
key_pem,
|
||||||
|
|||||||
+1648
-719
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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