mirror of
https://github.com/yhirose/cpp-httplib
synced 2026-06-08 18:30:49 +00:00
Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ad25b6cf0 | |||
| 3dff60eb16 | |||
| 5038314b21 | |||
| 6e1297cab0 | |||
| 7de743c962 | |||
| 964fb5e5ca | |||
| c4f3f9529b | |||
| 887def9490 | |||
| bad6b2d22f | |||
| 3d47a51430 | |||
| 0a2cb20223 | |||
| ce502a73e1 | |||
| 010e4479f4 | |||
| 70e193374a | |||
| 6b22409217 | |||
| 969cccd52a | |||
| 4a9c048bbc | |||
| bfabbec8c7 | |||
| 3e9c06cf79 | |||
| 29677540ae | |||
| 71fcfeb912 | |||
| c7d22e451f | |||
| 42f9f9107f | |||
| 7cd25fbd63 | |||
| 3dfb4ecac2 | |||
| 144114f316 | |||
| 0cc108d45e | |||
| 0743d78c9b | |||
| e022b8b80b | |||
| 34282c79a9 | |||
| f80b6bd980 | |||
| 5af7222217 | |||
| ec00fe5d5b | |||
| 24bdb736f0 | |||
| d0dc200633 | |||
| 919a51091f | |||
| 05e8b22989 | |||
| 00dcd6b004 | |||
| a42c6b99d3 | |||
| 812cb5bc3d | |||
| aea60feb85 | |||
| b3a4045300 | |||
| 5fcd8f7795 | |||
| d9fe3fa020 | |||
| d8612ac02d | |||
| 83ee6007da | |||
| 3eaa769a2d | |||
| b91540514d | |||
| ab563ff52c | |||
| 8cad160c0a | |||
| be7962f140 | |||
| 509b8570b0 | |||
| 630f3465a9 | |||
| 9af1a4a08f | |||
| 0654e5dab4 | |||
| 62e036f253 | |||
| f0adfb2e0c | |||
| 139c816c16 | |||
| 9505a76491 | |||
| 29fd136afd | |||
| f5598237b2 | |||
| 01058659ab | |||
| 66f698fab6 | |||
| b9a9df4d73 | |||
| 25aa3ca982 | |||
| 2d67211183 | |||
| f4c5d94d74 | |||
| 63a96aeb20 | |||
| bbb83d12c1 | |||
| 2d4b42b70b | |||
| 1919d08f71 | |||
| 824c02fcd3 | |||
| 2c0613f211 | |||
| be45ff1ff1 | |||
| 803ebe1e20 | |||
| ba685dbe48 | |||
| 49c4c2f9c1 | |||
| 58909f5917 | |||
| 5982b5c360 | |||
| eb1fe5b191 | |||
| 5e01587ed6 | |||
| 5935d9fa59 | |||
| 5bb4c12c6b | |||
| 85637844c9 | |||
| d043b18097 | |||
| 31bb13abd2 | |||
| 8728db7477 | |||
| 1c50ac3667 | |||
| cf386f97fd | |||
| b2203bb05a | |||
| f5b806d995 | |||
| 3895210f19 | |||
| d45250fd88 | |||
| 528cacdc0d | |||
| ed1b6afa10 | |||
| 08fc7085e5 | |||
| 8333340e2c | |||
| 98a0887571 | |||
| b0a189e50e | |||
| 776b3ffbf9 | |||
| a061b97677 | |||
| d359e3a5f7 | |||
| 5928e0af1a | |||
| a5005789ff | |||
| fae30af47d | |||
| 2feea0c9ab | |||
| a2e4af54b7 | |||
| d0b123be26 | |||
| df138366e4 | |||
| c49441ae64 | |||
| e1506fa186 | |||
| ad9fd3bd93 | |||
| 05e0253195 | |||
| da26b517a3 | |||
| 2b7a968468 | |||
| 240cc85ccb | |||
| 129e2f00b8 | |||
| da746c6e67 | |||
| 3451da940d | |||
| 38a6b3e69f | |||
| d1037ee9fd | |||
| 2ece5f116b | |||
| c2b6e4ac04 | |||
| 8674555b88 | |||
| 85327e19ae | |||
| ed8efea98b | |||
| 1ccddd1b0b | |||
| 992f3dc690 | |||
| 402d47e2cd | |||
| 171fc2e353 | |||
| ced4160d05 | |||
| 5b51aa6851 | |||
| dc13cde820 | |||
| b0af78e340 | |||
| 914c8860e8 | |||
| dc6a72a0fd | |||
| 685533ba50 | |||
| 6e46ccb37c | |||
| ac18b70a0f | |||
| e1acb949e7 | |||
| ab96f49766 | |||
| 7b3cea5317 | |||
| 26deffe0c6 | |||
| e07c5fec01 | |||
| 6e473a7c5c | |||
| c74129a1c2 | |||
| 18e750b4e7 | |||
| bf7700d192 | |||
| 3da925d6fe | |||
| 319417f26d | |||
| 4c3b119dde | |||
| 6de8684328 | |||
| ccc9a9b3f4 | |||
| f2bb9c45d6 | |||
| 9a663aa94e | |||
| d0d744d520 | |||
| fce8e6fefd | |||
| 180aa32ebf | |||
| fe01fa760b | |||
| d61d63dd97 | |||
| 3fe13ecc91 | |||
| 064cc6810e | |||
| 464cc89b77 | |||
| ca5a50d2c9 | |||
| b251668522 | |||
| 9ee740fe8f | |||
| 851edaf77f | |||
| 1a2a6e2b01 | |||
| ac7742bb32 | |||
| 82c11168c1 | |||
| 7c5197c86c | |||
| 8801e51138 |
@@ -3,6 +3,7 @@ tags
|
||||
example/server
|
||||
example/client
|
||||
example/hello
|
||||
example/simplecli
|
||||
example/simplesvr
|
||||
example/benchmark
|
||||
example/redirect
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
# Environment
|
||||
language: cpp
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
# Compiler selection
|
||||
compiler:
|
||||
- clang
|
||||
|
||||
# Build/test steps
|
||||
script:
|
||||
- cd ${TRAVIS_BUILD_DIR}/test
|
||||
- make all
|
||||
+264
-19
@@ -1,29 +1,274 @@
|
||||
cmake_minimum_required(VERSION 3.7.0)
|
||||
project(httplib)
|
||||
#[[
|
||||
Build options:
|
||||
* HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on)
|
||||
* HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on)
|
||||
* HTTPLIB_REQUIRE_OPENSSL (default off)
|
||||
* HTTPLIB_REQUIRE_ZLIB (default off)
|
||||
* HTTPLIB_COMPILE (default off)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
# Include
|
||||
After installation with Cmake, a find_package(httplib) is available.
|
||||
This creates a httplib::httplib target (if found).
|
||||
It can be linked like so:
|
||||
|
||||
target_link_libraries(your_exe httplib::httplib)
|
||||
|
||||
The following will build & install for later use.
|
||||
|
||||
Linux/macOS:
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
sudo cmake --build . --target install
|
||||
|
||||
Windows:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
runas /user:Administrator "cmake --build . --config Release --target install"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
These variables are available after you run find_package(httplib)
|
||||
* HTTPLIB_HEADER_PATH - this is the full path to the installed header (e.g. /usr/include/httplib.h).
|
||||
* 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_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).
|
||||
* HTTPLIB_VERSION - the project's version string.
|
||||
* HTTPLIB_FOUND - a bool for if the target was found.
|
||||
|
||||
Want to use precompiled headers (Cmake feature since v3.16)?
|
||||
It's as simple as doing the following (before linking):
|
||||
|
||||
target_precompile_headers(httplib::httplib INTERFACE "${HTTPLIB_HEADER_PATH}")
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
FindPython3 requires Cmake v3.12
|
||||
ARCH_INDEPENDENT option of write_basic_package_version_file() requires Cmake v3.14
|
||||
]]
|
||||
cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)
|
||||
|
||||
# Gets the latest tag as a string like "v0.6.6"
|
||||
# Can silently fail if git isn't on the system
|
||||
execute_process(COMMAND git describe --tags --abbrev=0
|
||||
OUTPUT_VARIABLE _raw_version_string
|
||||
ERROR_VARIABLE _git_tag_error
|
||||
)
|
||||
|
||||
# execute_process can fail silenty, so check for an error
|
||||
# if there was an error, just use the user agent as a version
|
||||
if(_git_tag_error)
|
||||
message(WARNING "cpp-httplib failed to find the latest git tag, falling back to using user agent as the version.")
|
||||
# Get the user agent and use it as a version
|
||||
# This gets the string with the user agent from the header.
|
||||
# This is so the maintainer doesn't actually need to update this manually.
|
||||
file(STRINGS httplib.h _raw_version_string REGEX "User\-Agent.*cpp\-httplib/([0-9]+\.?)+")
|
||||
endif()
|
||||
# Needed since git tags have "v" prefixing them.
|
||||
# Also used if the fallback to user agent string is being used.
|
||||
string(REGEX MATCH "([0-9]+\\.?)+" _httplib_version "${_raw_version_string}")
|
||||
|
||||
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 "1.1.1")
|
||||
|
||||
# Allow for a build to require OpenSSL to pass, instead of just being optional
|
||||
option(HTTPLIB_REQUIRE_OPENSSL "Requires OpenSSL to be found & linked, or fails build." OFF)
|
||||
option(HTTPLIB_REQUIRE_ZLIB "Requires ZLIB to be found & linked, or fails build." OFF)
|
||||
# Allow for a build to casually enable OpenSSL/ZLIB support, but silenty continue if not found.
|
||||
# Make these options so their automatic use can be specifically disabled (as needed)
|
||||
option(HTTPLIB_USE_OPENSSL_IF_AVAILABLE "Uses OpenSSL (if available) to enable HTTPS support." ON)
|
||||
option(HTTPLIB_USE_ZLIB_IF_AVAILABLE "Uses ZLIB (if available) to enable compression support." ON)
|
||||
# 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)
|
||||
# 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)
|
||||
# Necessary for Windows if building shared libs
|
||||
# See https://stackoverflow.com/a/40743080
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
endif()
|
||||
|
||||
# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
|
||||
find_package(Threads REQUIRED)
|
||||
# Since Cmake v3.11, Crypto & SSL became optional when not specified as COMPONENTS.
|
||||
if(HTTPLIB_REQUIRE_OPENSSL)
|
||||
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL REQUIRED)
|
||||
elseif(HTTPLIB_USE_OPENSSL_IF_AVAILABLE)
|
||||
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL QUIET)
|
||||
endif()
|
||||
if(HTTPLIB_REQUIRE_ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
elseif(HTTPLIB_USE_ZLIB_IF_AVAILABLE)
|
||||
find_package(ZLIB QUIET)
|
||||
endif()
|
||||
|
||||
# Used for default, common dirs that the end-user can change (if needed)
|
||||
# like CMAKE_INSTALL_INCLUDEDIR or CMAKE_INSTALL_DATADIR
|
||||
include(GNUInstallDirs)
|
||||
include(ExternalProject)
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_11)
|
||||
if(HTTPLIB_COMPILE)
|
||||
# Put the split script into the build dir
|
||||
configure_file(split.py "${CMAKE_CURRENT_BINARY_DIR}/split.py"
|
||||
COPYONLY
|
||||
)
|
||||
# Needs to be in the same dir as the python script
|
||||
configure_file(httplib.h "${CMAKE_CURRENT_BINARY_DIR}/httplib.h"
|
||||
COPYONLY
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
# Used outside of this if-else
|
||||
set(_INTERFACE_OR_PUBLIC PUBLIC)
|
||||
# Brings in the Python3_EXECUTABLE path we can use.
|
||||
find_package(Python3 REQUIRED)
|
||||
# Actually split the file
|
||||
# Keeps the output in the build dir to not pollute the main dir
|
||||
execute_process(COMMAND ${Python3_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/split.py"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
ERROR_VARIABLE _httplib_split_error
|
||||
)
|
||||
if(_httplib_split_error)
|
||||
message(FATAL_ERROR "Failed when trying to split Cpp-httplib with the Python script.\n${_httplib_split_error}")
|
||||
endif()
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} EXPORT httplibConfig
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
# split.py puts output in "out"
|
||||
set(_httplib_build_includedir "${CMAKE_CURRENT_BINARY_DIR}/out")
|
||||
# This will automatically be either static or shared based on the value of BUILD_SHARED_LIBS
|
||||
add_library(${PROJECT_NAME} "${_httplib_build_includedir}/httplib.cc")
|
||||
target_sources(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${_httplib_build_includedir}/httplib.h>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/httplib.h>
|
||||
)
|
||||
else()
|
||||
# This is for header-only.
|
||||
set(_INTERFACE_OR_PUBLIC INTERFACE)
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
set(_httplib_build_includedir "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
# Lets you address the target with httplib::httplib
|
||||
# Only useful if building in-tree, versus using it from an installation.
|
||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||
|
||||
install(FILES httplib.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
|
||||
# Might be missing some, but this list is somewhat comprehensive
|
||||
target_compile_features(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
cxx_std_11
|
||||
cxx_nullptr
|
||||
cxx_lambdas
|
||||
cxx_override
|
||||
cxx_defaulted_functions
|
||||
cxx_attribute_deprecated
|
||||
cxx_auto_type
|
||||
cxx_decltype
|
||||
cxx_deleted_functions
|
||||
cxx_range_for
|
||||
cxx_sizeof_member
|
||||
)
|
||||
|
||||
install(EXPORT httplibConfig DESTINATION share/httplib/cmake)
|
||||
target_include_directories(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
$<BUILD_INTERFACE:${_httplib_build_includedir}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
export(TARGETS ${PROJECT_NAME} FILE httplibConfig.cmake)
|
||||
# Always require threads
|
||||
target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
#add_subdirectory(example)
|
||||
#add_subdirectory(test)
|
||||
# We check for the target when using IF_AVAILABLE since it's possible we didn't find it.
|
||||
if(HTTPLIB_USE_OPENSSL_IF_AVAILABLE AND TARGET OpenSSL::SSL AND TARGET OpenSSL::Crypto OR HTTPLIB_REQUIRE_OPENSSL)
|
||||
target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
OpenSSL::SSL OpenSSL::Crypto
|
||||
)
|
||||
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
)
|
||||
set(HTTPLIB_IS_USING_OPENSSL TRUE)
|
||||
else()
|
||||
set(HTTPLIB_IS_USING_OPENSSL FALSE)
|
||||
endif()
|
||||
|
||||
# We check for the target when using IF_AVAILABLE since it's possible we didn't find it.
|
||||
if(HTTPLIB_USE_ZLIB_IF_AVAILABLE AND TARGET ZLIB::ZLIB OR HTTPLIB_REQUIRE_ZLIB)
|
||||
target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
ZLIB::ZLIB
|
||||
)
|
||||
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
||||
CPPHTTPLIB_ZLIB_SUPPORT
|
||||
)
|
||||
set(HTTPLIB_IS_USING_ZLIB TRUE)
|
||||
else()
|
||||
set(HTTPLIB_IS_USING_ZLIB FALSE)
|
||||
endif()
|
||||
|
||||
# Cmake's find_package search path is different based on the system
|
||||
# See https://cmake.org/cmake/help/latest/command/find_package.html for the list
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(_TARGET_INSTALL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/cmake/${PROJECT_NAME}")
|
||||
else()
|
||||
# On Non-Windows, it should be /usr/lib/cmake/<name>/<name>Config.cmake
|
||||
# NOTE: This may or may not work for macOS...
|
||||
set(_TARGET_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
# Configures the meta-file httplibConfig.cmake.in to replace variables with paths/values/etc.
|
||||
configure_package_config_file("${PROJECT_NAME}Config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION "${_TARGET_INSTALL_CMAKEDIR}"
|
||||
# Passes the includedir install path
|
||||
PATH_VARS CMAKE_INSTALL_FULL_INCLUDEDIR
|
||||
# There aren't any components, so don't use the macro
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
)
|
||||
|
||||
if(HTTPLIB_COMPILE)
|
||||
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
||||
# Example: if you find_package(httplib 0.5.4)
|
||||
# then anything >= 0.5 and <= 1.0 is accepted
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
else()
|
||||
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
||||
# Example: if you find_package(httplib 0.5.4)
|
||||
# then anything >= 0.5 and <= 1.0 is accepted
|
||||
COMPATIBILITY SameMajorVersion
|
||||
# Tells Cmake that it's a header-only lib
|
||||
# Mildly useful for end-users :)
|
||||
ARCH_INDEPENDENT
|
||||
)
|
||||
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
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
install(FILES "${_httplib_build_includedir}/httplib.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
|
||||
)
|
||||
|
||||
# NOTE: This path changes depending on if it's on Windows or Linux
|
||||
install(EXPORT httplibTargets
|
||||
# Puts the targets into the httplib namespace
|
||||
# So this makes httplib::httplib linkable after doing find_package(httplib)
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
|
||||
)
|
||||
|
||||
@@ -2,13 +2,14 @@ cpp-httplib
|
||||
===========
|
||||
|
||||
[](https://github.com/yhirose/cpp-httplib/actions)
|
||||
[](https://travis-ci.org/yhirose/cpp-httplib)
|
||||
[](https://ci.appveyor.com/project/yhirose/cpp-httplib)
|
||||
|
||||
A C++11 single-file header-only cross platform HTTP/HTTPS library.
|
||||
|
||||
It's extremely easy to setup. Just include **httplib.h** file in your code!
|
||||
|
||||
For Windows users: Please read [this note](https://github.com/yhirose/cpp-httplib#windows).
|
||||
|
||||
Server Example
|
||||
--------------
|
||||
|
||||
@@ -17,24 +18,34 @@ Server Example
|
||||
|
||||
int main(void)
|
||||
{
|
||||
using namespace httplib;
|
||||
using namespace httplib;
|
||||
|
||||
Server svr;
|
||||
Server svr;
|
||||
|
||||
svr.Get("/hi", [](const Request& req, Response& res) {
|
||||
res.set_content("Hello World!", "text/plain");
|
||||
});
|
||||
svr.Get("/hi", [](const Request& req, Response& res) {
|
||||
res.set_content("Hello World!", "text/plain");
|
||||
});
|
||||
|
||||
svr.Get(R"(/numbers/(\d+))", [&](const Request& req, Response& res) {
|
||||
auto numbers = req.matches[1];
|
||||
res.set_content(numbers, "text/plain");
|
||||
});
|
||||
svr.Get(R"(/numbers/(\d+))", [&](const Request& req, Response& res) {
|
||||
auto numbers = req.matches[1];
|
||||
res.set_content(numbers, "text/plain");
|
||||
});
|
||||
|
||||
svr.Get("/stop", [&](const Request& req, Response& res) {
|
||||
svr.stop();
|
||||
});
|
||||
svr.Get("/body-header-param", [](const Request& req, Response& res) {
|
||||
if (req.has_header("Content-Length")) {
|
||||
auto val = req.get_header_value("Content-Length");
|
||||
}
|
||||
if (req.has_param("key")) {
|
||||
auto val = req.get_param_value("key");
|
||||
}
|
||||
res.set_content(req.body, "text/plain");
|
||||
});
|
||||
|
||||
svr.listen("localhost", 1234);
|
||||
svr.Get("/stop", [&](const Request& req, Response& res) {
|
||||
svr.stop();
|
||||
});
|
||||
|
||||
svr.listen("localhost", 1234);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -50,17 +61,24 @@ svr.listen_after_bind();
|
||||
### Static File Server
|
||||
|
||||
```cpp
|
||||
auto ret = svr.set_base_dir("./www"); // This is same as `svr.set_base_dir("./www", "/")`;
|
||||
// Mount / to ./www directory
|
||||
auto ret = svr.set_mount_point("/", "./www");
|
||||
if (!ret) {
|
||||
// The specified base directory doesn't exist...
|
||||
}
|
||||
|
||||
// Mount /public to ./www directory
|
||||
ret = svr.set_base_dir("./www", "/public");
|
||||
ret = svr.set_mount_point("/public", "./www");
|
||||
|
||||
// Mount /public to ./www1 and ./www2 directories
|
||||
ret = svr.set_base_dir("./www1", "/public"); // 1st order to search
|
||||
ret = svr.set_base_dir("./www2", "/public"); // 2nd order to search
|
||||
ret = svr.set_mount_point("/public", "./www1"); // 1st order to search
|
||||
ret = svr.set_mount_point("/public", "./www2"); // 2nd order to search
|
||||
|
||||
// Remove mount /
|
||||
ret = svr.remove_mount_point("/");
|
||||
|
||||
// Remove mount /public
|
||||
ret = svr.remove_mount_point("/public");
|
||||
```
|
||||
|
||||
```cpp
|
||||
@@ -72,39 +90,41 @@ svr.set_file_extension_and_mimetype_mapping("hh", "text/x-h");
|
||||
|
||||
The followings are built-in mappings:
|
||||
|
||||
| Extension | MIME Type |
|
||||
| :--------- | :--------------------- |
|
||||
| .txt | text/plain |
|
||||
| .html .htm | text/html |
|
||||
| .css | text/css |
|
||||
| .jpeg .jpg | image/jpg |
|
||||
| .png | image/png |
|
||||
| .gif | image/gif |
|
||||
| .svg | image/svg+xml |
|
||||
| .ico | image/x-icon |
|
||||
| .json | application/json |
|
||||
| .pdf | application/pdf |
|
||||
| .js | application/javascript |
|
||||
| .wasm | application/wasm |
|
||||
| .xml | application/xml |
|
||||
| .xhtml | application/xhtml+xml |
|
||||
| Extension | MIME Type |
|
||||
| :-------- | :--------------------- |
|
||||
| txt | text/plain |
|
||||
| html, htm | text/html |
|
||||
| css | text/css |
|
||||
| jpeg, jpg | image/jpg |
|
||||
| png | image/png |
|
||||
| gif | image/gif |
|
||||
| svg | image/svg+xml |
|
||||
| ico | image/x-icon |
|
||||
| json | application/json |
|
||||
| pdf | application/pdf |
|
||||
| js | application/javascript |
|
||||
| wasm | application/wasm |
|
||||
| xml | application/xml |
|
||||
| xhtml | application/xhtml+xml |
|
||||
|
||||
NOTE: These the static file server methods are not thread safe.
|
||||
|
||||
### Logging
|
||||
|
||||
```cpp
|
||||
svr.set_logger([](const auto& req, const auto& res) {
|
||||
your_logger(req, res);
|
||||
your_logger(req, res);
|
||||
});
|
||||
```
|
||||
|
||||
### Error Handler
|
||||
### Error handler
|
||||
|
||||
```cpp
|
||||
svr.set_error_handler([](const auto& req, auto& res) {
|
||||
auto fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
|
||||
char buf[BUFSIZ];
|
||||
snprintf(buf, sizeof(buf), fmt, res.status);
|
||||
res.set_content(buf, "text/html");
|
||||
auto fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
|
||||
char buf[BUFSIZ];
|
||||
snprintf(buf, sizeof(buf), fmt, res.status);
|
||||
res.set_content(buf, "text/html");
|
||||
});
|
||||
```
|
||||
|
||||
@@ -112,31 +132,12 @@ svr.set_error_handler([](const auto& req, auto& res) {
|
||||
|
||||
```cpp
|
||||
svr.Post("/multipart", [&](const auto& req, auto& res) {
|
||||
auto size = req.files.size();
|
||||
auto ret = req.has_file("name1");
|
||||
const auto& file = req.get_file_value("name1");
|
||||
// file.filename;
|
||||
// file.content_type;
|
||||
// file.content;
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
### Send content with Content provider
|
||||
|
||||
```cpp
|
||||
const uint64_t DATA_CHUNK_SIZE = 4;
|
||||
|
||||
svr.Get("/stream", [&](const Request &req, Response &res) {
|
||||
auto data = new std::string("abcdefg");
|
||||
|
||||
res.set_content_provider(
|
||||
data->size(), // Content length
|
||||
[data](uint64_t offset, uint64_t length, DataSink &sink) {
|
||||
const auto &d = *data;
|
||||
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
|
||||
},
|
||||
[data] { delete data; });
|
||||
auto size = req.files.size();
|
||||
auto ret = req.has_file("name1");
|
||||
const auto& file = req.get_file_value("name1");
|
||||
// file.filename;
|
||||
// file.content_type;
|
||||
// file.content;
|
||||
});
|
||||
```
|
||||
|
||||
@@ -167,21 +168,79 @@ svr.Post("/content_receiver",
|
||||
});
|
||||
```
|
||||
|
||||
### Send content with Content provider
|
||||
|
||||
```cpp
|
||||
const size_t DATA_CHUNK_SIZE = 4;
|
||||
|
||||
svr.Get("/stream", [&](const Request &req, Response &res) {
|
||||
auto data = new std::string("abcdefg");
|
||||
|
||||
res.set_content_provider(
|
||||
data->size(), // Content length
|
||||
[data](size_t offset, size_t length, DataSink &sink) {
|
||||
const auto &d = *data;
|
||||
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
|
||||
return true; // return 'false' if you want to cancel the process.
|
||||
},
|
||||
[data] { delete data; });
|
||||
});
|
||||
```
|
||||
|
||||
### Chunked transfer encoding
|
||||
|
||||
```cpp
|
||||
svr.Get("/chunked", [&](const Request& req, Response& res) {
|
||||
res.set_chunked_content_provider(
|
||||
[](uint64_t offset, DataSink &sink) {
|
||||
sink.write("123", 3);
|
||||
sink.write("345", 3);
|
||||
sink.write("789", 3);
|
||||
sink.done();
|
||||
[](size_t offset, DataSink &sink) {
|
||||
sink.write("123", 3);
|
||||
sink.write("345", 3);
|
||||
sink.write("789", 3);
|
||||
sink.done();
|
||||
return true; // return 'false' if you want to cancel the process.
|
||||
}
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
### 'Expect: 100-continue' handler
|
||||
|
||||
As default, the server sends `100 Continue` response for `Expect: 100-continue` header.
|
||||
|
||||
```cpp
|
||||
// Send a '417 Expectation Failed' response.
|
||||
svr.set_expect_100_continue_handler([](const Request &req, Response &res) {
|
||||
return 417;
|
||||
});
|
||||
```
|
||||
|
||||
```cpp
|
||||
// Send a final status without reading the message body.
|
||||
svr.set_expect_100_continue_handler([](const Request &req, Response &res) {
|
||||
return res.status = 401;
|
||||
});
|
||||
```
|
||||
|
||||
### Keep-Alive connection
|
||||
|
||||
```cpp
|
||||
svr.set_keep_alive_max_count(2); // Default is 5
|
||||
```
|
||||
|
||||
### Timeout
|
||||
|
||||
```c++
|
||||
svr.set_read_timeout(5, 0); // 5 seconds
|
||||
svr.set_write_timeout(5, 0); // 5 seconds
|
||||
svr.set_idle_interval(0, 100000); // 100 milliseconds
|
||||
```
|
||||
|
||||
### Set maximum payload length for reading request body
|
||||
|
||||
```c++
|
||||
svr.set_payload_max_length(1024 * 1024 * 512); // 512MB
|
||||
```
|
||||
|
||||
### Server-Sent Events
|
||||
|
||||
Please check [here](https://github.com/yhirose/cpp-httplib/blob/master/example/sse.cc).
|
||||
@@ -191,11 +250,7 @@ Please check [here](https://github.com/yhirose/cpp-httplib/blob/master/example/s
|
||||
|
||||
`ThreadPool` is used as a default task queue, and the default thread count is set to value from `std::thread::hardware_concurrency()`.
|
||||
|
||||
Set thread count to 8:
|
||||
|
||||
```cpp
|
||||
#define CPPHTTPLIB_THREAD_POOL_COUNT 8
|
||||
```
|
||||
You can change the thread count by setting `CPPHTTPLIB_THREAD_POOL_COUNT`.
|
||||
|
||||
### Override the default thread pool with yours
|
||||
|
||||
@@ -226,44 +281,43 @@ svr.new_task_queue = [] {
|
||||
Client Example
|
||||
--------------
|
||||
|
||||
### GET
|
||||
|
||||
```c++
|
||||
#include <httplib.h>
|
||||
#include <iostream>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
httplib::Client cli("localhost", 1234);
|
||||
// IMPORTANT: 1st parameter must be a hostname or an IP address string.
|
||||
httplib::Client cli("localhost", 1234);
|
||||
|
||||
auto res = cli.Get("/hi");
|
||||
if (res && res->status == 200) {
|
||||
std::cout << res->body << std::endl;
|
||||
}
|
||||
auto res = cli.Get("/hi");
|
||||
if (res && res->status == 200) {
|
||||
std::cout << res->body << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET with HTTP headers
|
||||
|
||||
```c++
|
||||
httplib::Headers headers = {
|
||||
{ "Accept-Encoding", "gzip, deflate" }
|
||||
};
|
||||
auto res = cli.Get("/hi", headers);
|
||||
httplib::Headers headers = {
|
||||
{ "Accept-Encoding", "gzip, deflate" }
|
||||
};
|
||||
auto res = cli.Get("/hi", headers);
|
||||
```
|
||||
|
||||
### GET with Content Receiver
|
||||
|
||||
```c++
|
||||
std::string body;
|
||||
std::string body;
|
||||
|
||||
auto res = cli.Get("/large-data",
|
||||
[&](const char *data, uint64_t data_length) {
|
||||
body.append(data, data_length);
|
||||
return true;
|
||||
});
|
||||
auto res = cli.Get("/large-data",
|
||||
[&](const char *data, size_t data_length) {
|
||||
body.append(data, data_length);
|
||||
return true;
|
||||
});
|
||||
|
||||
assert(res->body.empty());
|
||||
assert(res->body.empty());
|
||||
```
|
||||
|
||||
### POST
|
||||
@@ -296,15 +350,15 @@ auto res = cli.Post("/post", params);
|
||||
### POST with Multipart Form Data
|
||||
|
||||
```c++
|
||||
httplib::MultipartFormDataItems items = {
|
||||
{ "text1", "text default", "", "" },
|
||||
{ "text2", "aωb", "", "" },
|
||||
{ "file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain" },
|
||||
{ "file2", "{\n \"world\", true\n}\n", "world.json", "application/json" },
|
||||
{ "file3", "", "", "application/octet-stream" },
|
||||
};
|
||||
httplib::MultipartFormDataItems items = {
|
||||
{ "text1", "text default", "", "" },
|
||||
{ "text2", "aωb", "", "" },
|
||||
{ "file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain" },
|
||||
{ "file2", "{\n \"world\", true\n}\n", "world.json", "application/json" },
|
||||
{ "file3", "", "", "application/octet-stream" },
|
||||
};
|
||||
|
||||
auto res = cli.Post("/multipart", items);
|
||||
auto res = cli.Post("/multipart", items);
|
||||
```
|
||||
|
||||
### PUT
|
||||
@@ -326,11 +380,43 @@ res = cli.Options("*");
|
||||
res = cli.Options("/resource/foo");
|
||||
```
|
||||
|
||||
### Connection Timeout
|
||||
### Timeout
|
||||
|
||||
```c++
|
||||
cli.set_timeout_sec(5); // timeouts in 5 seconds
|
||||
cli.set_connection_timeout(0, 300000); // 300 milliseconds
|
||||
cli.set_read_timeout(5, 0); // 5 seconds
|
||||
cli.set_write_timeout(5, 0); // 5 seconds
|
||||
```
|
||||
|
||||
### Receive content with Content receiver
|
||||
|
||||
```cpp
|
||||
std::string body;
|
||||
auto res = cli.Get(
|
||||
"/stream", Headers(),
|
||||
[&](const Response &response) {
|
||||
EXPECT_EQ(200, response.status);
|
||||
return true; // return 'false' if you want to cancel the request.
|
||||
},
|
||||
[&](const char *data, size_t data_length) {
|
||||
body.append(data, data_length);
|
||||
return true; // return 'false' if you want to cancel the request.
|
||||
});
|
||||
```
|
||||
|
||||
### Send content with Content provider
|
||||
|
||||
```cpp
|
||||
std::string body = ...;
|
||||
auto res = cli_.Post(
|
||||
"/stream", body.size(),
|
||||
[](size_t offset, size_t length, DataSink &sink) {
|
||||
sink.write(body.data() + offset, length);
|
||||
return true; // return 'false' if you want to cancel the request.
|
||||
},
|
||||
"text/plain");
|
||||
```
|
||||
|
||||
### With Progress Callback
|
||||
|
||||
```cpp
|
||||
@@ -338,12 +424,12 @@ httplib::Client client(url, port);
|
||||
|
||||
// prints: 0 / 000 bytes => 50% complete
|
||||
std::shared_ptr<httplib::Response> res =
|
||||
cli.Get("/", [](uint64_t len, uint64_t total) {
|
||||
printf("%lld / %lld bytes => %d%% complete\n",
|
||||
len, total,
|
||||
(int)((len/total)*100));
|
||||
return true; // return 'false' if you want to cancel the request.
|
||||
}
|
||||
cli.Get("/", [](uint64_t len, uint64_t total) {
|
||||
printf("%lld / %lld bytes => %d%% complete\n",
|
||||
len, total,
|
||||
(int)(len*100/total));
|
||||
return true; // return 'false' if you want to cancel the request.
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
@@ -396,20 +482,15 @@ httplib::make_range_header({{0, 0}, {-1, 1}}) // 'Range: bytes=0-0, -1'
|
||||
### Keep-Alive connection
|
||||
|
||||
```cpp
|
||||
cli.set_keep_alive_max_count(2); // Default is 5
|
||||
httplib::Client cli("localhost", 1234);
|
||||
|
||||
std::vector<Request> requests;
|
||||
Get(requests, "/get-request1");
|
||||
Get(requests, "/get-request2");
|
||||
Post(requests, "/post-request1", "text", "text/plain");
|
||||
Post(requests, "/post-request2", "text", "text/plain");
|
||||
cli.Get("/hello"); // with "Connection: close"
|
||||
|
||||
std::vector<Response> responses;
|
||||
if (cli.send(requests, responses)) {
|
||||
for (const auto& res: responses) {
|
||||
...
|
||||
}
|
||||
}
|
||||
cli.set_keep_alive(true);
|
||||
cli.Get("/world");
|
||||
|
||||
cli.set_keep_alive(false);
|
||||
cli.Get("/last-request"); // with "Connection: close"
|
||||
```
|
||||
|
||||
### Redirect
|
||||
@@ -453,7 +534,7 @@ cli.enable_server_certificate_verification(true);
|
||||
Zlib Support
|
||||
------------
|
||||
|
||||
'gzip' compression is available with `CPPHTTPLIB_ZLIB_SUPPORT`.
|
||||
'gzip' compression is available with `CPPHTTPLIB_ZLIB_SUPPORT`. `libz` should be linked.
|
||||
|
||||
The server applies gzip compression to the following MIME type contents:
|
||||
|
||||
@@ -464,13 +545,21 @@ The server applies gzip compression to the following MIME type contents:
|
||||
* application/xml
|
||||
* application/xhtml+xml
|
||||
|
||||
### Compress content on client
|
||||
### Compress request body on client
|
||||
|
||||
```c++
|
||||
cli.set_compress(true);
|
||||
res = cli.Post("/resource/foo", "...", "text/plain");
|
||||
```
|
||||
|
||||
### Compress response body on client
|
||||
|
||||
```c++
|
||||
cli.set_decompress(false);
|
||||
res = cli.Get("/resource/foo", {{"Accept-Encoding", "gzip, deflate"}});
|
||||
res->body; // Compressed data
|
||||
```
|
||||
|
||||
Split httplib.h into .h and .cc
|
||||
-------------------------------
|
||||
|
||||
@@ -483,8 +572,27 @@ httplib.h httplib.cc
|
||||
NOTE
|
||||
----
|
||||
|
||||
### g++
|
||||
|
||||
g++ 4.8 and below cannot build this library since `<regex>` in the versions are [broken](https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions).
|
||||
|
||||
### Windows
|
||||
|
||||
Include `httplib.h` before `Windows.h` or include `Windows.h` by defining `WIN32_LEAN_AND_MEAN` beforehand.
|
||||
|
||||
```cpp
|
||||
#include <httplib.h>
|
||||
#include <Windows.h>
|
||||
```
|
||||
|
||||
```cpp
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <httplib.h>
|
||||
```
|
||||
|
||||
Note: Cygwin on Windows is not supported.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
@@ -493,42 +601,4 @@ MIT license (© 2020 Yuji Hirose)
|
||||
Special Thanks To
|
||||
-----------------
|
||||
|
||||
The following folks made great contributions to polish this library to totally another level from a simple toy!
|
||||
|
||||
* [Zefz](https://github.com/Zefz)
|
||||
* [PixlRainbow](https://github.com/PixlRainbow)
|
||||
* [sgraham](https://github.com/sgraham)
|
||||
* [mrexodia](https://github.com/mrexodia)
|
||||
* [hyperxor](https://github.com/hyperxor)
|
||||
* [omaralvarez](https://github.com/omaralvarez)
|
||||
* [vvanelslande](https://github.com/vvanelslande)
|
||||
* [underscorediscovery](https://github.com/underscorediscovery)
|
||||
* [sux2mfgj](https://github.com/sux2mfgj)
|
||||
* [matvore](https://github.com/matvore)
|
||||
* [intmain-io](https://github.com/intmain)
|
||||
* [davidgfnet](https://github.com/davidgfnet)
|
||||
* [crtxcr](https://github.com/crtxcr)
|
||||
* [const-volatile](https://github.com/const)
|
||||
* [aguadoenzo](https://github.com/aguadoenzo)
|
||||
* [TheMaverickProgrammer](https://github.com/TheMaverickProgrammer)
|
||||
* [vdudouyt](https://github.com/vdudouyt)
|
||||
* [stupedama](https://github.com/stupedama)
|
||||
* [rockwotj](https://github.com/rockwotj)
|
||||
* [marknelson](https://github.com/marknelson)
|
||||
* [jaspervandeven](https://github.com/jaspervandeven)
|
||||
* [hans-erickson](https://github.com/hans)
|
||||
* [ha11owed](https://github.com/ha11owed)
|
||||
* [gulrak](https://github.com/gulrak)
|
||||
* [dolphineye](https://github.com/dolphineye)
|
||||
* [danielzehe](https://github.com/danielzehe)
|
||||
* [batist73](https://github.com/batist73)
|
||||
* [barryam3](https://github.com/barryam3)
|
||||
* [adikabintang](https://github.com/adikabintang)
|
||||
* [aaronalbers](https://github.com/aaronalbers)
|
||||
* [Whitetigerswt](https://github.com/Whitetigerswt)
|
||||
* [TangHuaiZhe](https://github.com/TangHuaiZhe)
|
||||
* [Sil3ntStorm](https://github.com/Sil3ntStorm)
|
||||
* [MannyClicks](https://github.com/MannyClicks)
|
||||
* [DraTeots](https://github.com/DraTeots)
|
||||
* [BastienDurel](https://github.com/BastienDurel)
|
||||
* [vitalyster](https://github.com/vitalyster)
|
||||
[These folks](https://github.com/yhirose/cpp-httplib/graphs/contributors) made great contributions to polish this library to totally another level from a simple toy!
|
||||
|
||||
+12
-7
@@ -1,9 +1,14 @@
|
||||
version: 1.0.{build}
|
||||
image: Visual Studio 2017
|
||||
build_script:
|
||||
- cmd: >-
|
||||
cd test
|
||||
image:
|
||||
- Visual Studio 2019
|
||||
|
||||
platform:
|
||||
- x64
|
||||
|
||||
build_script:
|
||||
- cmd: >-
|
||||
cd test
|
||||
|
||||
msbuild.exe test.sln /verbosity:minimal /t:Build /p:Configuration=Release;Platform=%PLATFORM%
|
||||
|
||||
msbuild.exe test.sln /verbosity:minimal /t:Build /p:Configuration=Debug;Platform=Win32
|
||||
test_script:
|
||||
- cmd: Debug\test.exe
|
||||
- cmd: x64\Release\test.exe
|
||||
|
||||
+5
-2
@@ -5,7 +5,7 @@ OPENSSL_DIR = /usr/local/opt/openssl
|
||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
||||
|
||||
all: server client hello simplesvr upload redirect sse benchmark
|
||||
all: server client hello simplecli simplesvr upload redirect sse benchmark
|
||||
|
||||
server : server.cc ../httplib.h Makefile
|
||||
$(CXX) -o server $(CXXFLAGS) server.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||
@@ -16,6 +16,9 @@ client : client.cc ../httplib.h Makefile
|
||||
hello : hello.cc ../httplib.h Makefile
|
||||
$(CXX) -o hello $(CXXFLAGS) hello.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||
|
||||
simplecli : simplecli.cc ../httplib.h Makefile
|
||||
$(CXX) -o simplecli $(CXXFLAGS) simplecli.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||
|
||||
simplesvr : simplesvr.cc ../httplib.h Makefile
|
||||
$(CXX) -o simplesvr $(CXXFLAGS) simplesvr.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
|
||||
|
||||
@@ -36,4 +39,4 @@ pem:
|
||||
openssl req -new -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem
|
||||
|
||||
clean:
|
||||
rm server client hello simplesvr upload redirect sse benchmark *.pem
|
||||
rm server client hello simplecli simplesvr upload redirect sse benchmark *.pem
|
||||
|
||||
+1
-1
@@ -15,5 +15,5 @@ int main(void) {
|
||||
res.set_content("Hello World!", "text/plain");
|
||||
});
|
||||
|
||||
svr.listen("localhost", 1234);
|
||||
svr.listen("localhost", 8080);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// simplecli.cc
|
||||
//
|
||||
// Copyright (c) 2019 Yuji Hirose. All rights reserved.
|
||||
// MIT License
|
||||
//
|
||||
|
||||
#include <httplib.h>
|
||||
#include <iostream>
|
||||
|
||||
#define CA_CERT_FILE "./ca-bundle.crt"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(void) {
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
auto res = httplib::Client2("https://localhost:8080")
|
||||
.set_ca_cert_path(CA_CERT_FILE)
|
||||
// .enable_server_certificate_verification(true)
|
||||
.Get("/hi");
|
||||
#else
|
||||
auto res = httplib::Client2("http://localhost:8080").Get("/hi");
|
||||
#endif
|
||||
|
||||
if (res) {
|
||||
cout << res->status << endl;
|
||||
cout << res->get_header_value("Content-Type") << endl;
|
||||
cout << res->body << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -122,12 +122,12 @@ int main(int argc, const char **argv) {
|
||||
auto base_dir = "./";
|
||||
if (argc > 2) { base_dir = argv[2]; }
|
||||
|
||||
if (!svr.set_base_dir(base_dir)) {
|
||||
if (!svr.set_mount_point("/", base_dir)) {
|
||||
cout << "The specified base directory doesn't exist...";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cout << "The server started at port " << port << "...";
|
||||
cout << "The server started at port " << port << "..." << endl;
|
||||
|
||||
svr.listen("localhost", port);
|
||||
|
||||
|
||||
+9
-4
@@ -11,6 +11,7 @@
|
||||
#include <httplib.h>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
using namespace httplib;
|
||||
@@ -79,15 +80,19 @@ int main(void) {
|
||||
svr.Get("/event1", [&](const Request & /*req*/, Response &res) {
|
||||
cout << "connected to event1..." << endl;
|
||||
res.set_header("Content-Type", "text/event-stream");
|
||||
res.set_chunked_content_provider(
|
||||
[&](uint64_t /*offset*/, DataSink &sink) { ed.wait_event(&sink); });
|
||||
res.set_chunked_content_provider([&](size_t /*offset*/, DataSink &sink) {
|
||||
ed.wait_event(&sink);
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
svr.Get("/event2", [&](const Request & /*req*/, Response &res) {
|
||||
cout << "connected to event2..." << endl;
|
||||
res.set_header("Content-Type", "text/event-stream");
|
||||
res.set_chunked_content_provider(
|
||||
[&](uint64_t /*offset*/, DataSink &sink) { ed.wait_event(&sink); });
|
||||
res.set_chunked_content_provider([&](size_t /*offset*/, DataSink &sink) {
|
||||
ed.wait_event(&sink);
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
thread t([&] {
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Generates a macro to auto-configure everything
|
||||
@PACKAGE_INIT@
|
||||
|
||||
# Setting these here so they're accessible after install.
|
||||
# Might be useful for some users to check which settings were used.
|
||||
set(HTTPLIB_IS_USING_OPENSSL @HTTPLIB_IS_USING_OPENSSL@)
|
||||
set(HTTPLIB_IS_USING_ZLIB @HTTPLIB_IS_USING_ZLIB@)
|
||||
set(HTTPLIB_IS_COMPILED @HTTPLIB_COMPILE@)
|
||||
set(HTTPLIB_VERSION @PROJECT_VERSION@)
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
# We add find_dependency calls here to not make the end-user have to call them.
|
||||
find_dependency(Threads REQUIRED)
|
||||
if(@HTTPLIB_IS_USING_OPENSSL@)
|
||||
# OpenSSL COMPONENTS were added in Cmake v3.11
|
||||
if(CMAKE_VERSION VERSION_LESS "3.11")
|
||||
find_dependency(OpenSSL @_HTTPLIB_OPENSSL_MIN_VER@ REQUIRED)
|
||||
else()
|
||||
# Once the COMPONENTS were added, they were made optional when not specified.
|
||||
# Since we use both, we need to search for both.
|
||||
find_dependency(OpenSSL @_HTTPLIB_OPENSSL_MIN_VER@ COMPONENTS Crypto SSL REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
if(@HTTPLIB_IS_USING_ZLIB@)
|
||||
find_dependency(ZLIB REQUIRED)
|
||||
endif()
|
||||
|
||||
# Mildly useful for end-users
|
||||
# Not really recommended to be used though
|
||||
set_and_check(HTTPLIB_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||
# Lets the end-user find the header path with the header appended
|
||||
# This is helpful if you're using Cmake's pre-compiled header feature
|
||||
set_and_check(HTTPLIB_HEADER_PATH "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@/httplib.h")
|
||||
|
||||
# Brings in the target library
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/httplibTargets.cmake")
|
||||
|
||||
# Ouputs a "found httplib /usr/include/httplib.h" message when using find_package(httplib)
|
||||
include(FindPackageMessage)
|
||||
if(TARGET httplib::httplib)
|
||||
set(HTTPLIB_FOUND TRUE)
|
||||
|
||||
# Since the compiled version has a lib, show that in the message
|
||||
if(@HTTPLIB_COMPILE@)
|
||||
# The list of configurations is most likely just 1 unless they installed a debug & release
|
||||
get_target_property(_httplib_configs httplib::httplib "IMPORTED_CONFIGURATIONS")
|
||||
# Need to loop since the "IMPORTED_LOCATION" property isn't want we want.
|
||||
# Instead, we need to find the IMPORTED_LOCATION_RELEASE or IMPORTED_LOCATION_DEBUG which has the lib path.
|
||||
foreach(_httplib_conf "${_httplib_configs}")
|
||||
# Grab the path to the lib and sets it to HTTPLIB_LIBRARY
|
||||
get_target_property(HTTPLIB_LIBRARY httplib::httplib "IMPORTED_LOCATION_${_httplib_conf}")
|
||||
# Check if we found it
|
||||
if(HTTPLIB_LIBRARY)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
unset(_httplib_configs)
|
||||
unset(_httplib_conf)
|
||||
|
||||
find_package_message(httplib "Found httplib: ${HTTPLIB_LIBRARY} (found version \"${HTTPLIB_VERSION}\")" "[${HTTPLIB_LIBRARY}][${HTTPLIB_HEADER_PATH}]")
|
||||
else()
|
||||
find_package_message(httplib "Found httplib: ${HTTPLIB_HEADER_PATH} (found version \"${HTTPLIB_VERSION}\")" "[${HTTPLIB_HEADER_PATH}]")
|
||||
endif()
|
||||
endif()
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
|
||||
#CXX = clang++
|
||||
CXXFLAGS = -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits
|
||||
CXXFLAGS = -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits -Wconversion
|
||||
OPENSSL_DIR = /usr/local/opt/openssl
|
||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
|
||||
|
||||
+14
-1
@@ -38,6 +38,14 @@
|
||||
// when it's fused.
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#if __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion"
|
||||
#elif __GNUC__
|
||||
#pragma gcc diagnostic push
|
||||
#pragma gcc diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
// The following lines pull in the real gtest *.cc files.
|
||||
// Copyright 2005, Google Inc.
|
||||
// All rights reserved.
|
||||
@@ -9039,7 +9047,6 @@ void HasNewFatalFailureHelper::ReportTestPartResult(
|
||||
//
|
||||
// Author: wan@google.com (Zhanyong Wan)
|
||||
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
@@ -9116,3 +9123,9 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#if __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#elif __GNUC__
|
||||
#pragma gcc diagnostic pop
|
||||
#endif
|
||||
|
||||
+15
-1
@@ -59,6 +59,14 @@
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
#if __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wsign-compare"
|
||||
#elif __GNUC__
|
||||
#pragma gcc diagnostic push
|
||||
#pragma gcc diagnostic ignored "-Wsign-compare"
|
||||
#endif
|
||||
|
||||
// Copyright 2005, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -7311,7 +7319,7 @@ inline const char* SkipComma(const char* str) {
|
||||
// the entire string if it contains no comma.
|
||||
inline String GetPrefixUntilComma(const char* str) {
|
||||
const char* comma = strchr(str, ',');
|
||||
return comma == NULL ? String(str) : String(str, comma - str);
|
||||
return comma == NULL ? String(str) : String(str, static_cast<size_t>(comma - str));
|
||||
}
|
||||
|
||||
// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
|
||||
@@ -19553,4 +19561,10 @@ bool StaticAssertTypeEq() {
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
#if __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#elif __GNUC__
|
||||
#pragma gcc diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
|
||||
|
||||
+822
-135
File diff suppressed because it is too large
Load Diff
+13
-13
@@ -28,7 +28,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
@@ -40,7 +40,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -69,13 +69,13 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>C:\Program Files\OpenSSL-Win64\lib\VC;C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Program Files\OpenSSL-Win64\lib;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
@@ -84,14 +84,14 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Program Files\OpenSSL-Win64\lib;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
||||
@@ -108,7 +108,7 @@
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
|
||||
@@ -118,12 +118,12 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>Ws2_32.lib;libssl.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
@@ -144,7 +144,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
@@ -160,7 +160,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>Ws2_32.lib;libssl.lib;libcrypto.lib;libssl.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
+38
-54
@@ -52,6 +52,7 @@ void RedirectProxyText(Client& cli, const char *path, bool basic) {
|
||||
EXPECT_EQ(200, res->status);
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST(RedirectTest, HTTPBinNoSSLBasic) {
|
||||
Client cli("httpbin.org");
|
||||
RedirectProxyText(cli, "/redirect/2", true);
|
||||
@@ -73,6 +74,7 @@ TEST(RedirectTest, HTTPBinSSLDigest) {
|
||||
RedirectProxyText(cli, "/redirect/2", false);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
TEST(RedirectTest, YouTubeNoSSLBasic) {
|
||||
@@ -185,15 +187,17 @@ void DigestAuthTestFromHTTPWatch(Client& cli) {
|
||||
for (auto path : paths) {
|
||||
auto res = cli.Get(path.c_str());
|
||||
ASSERT_TRUE(res != nullptr);
|
||||
EXPECT_EQ(400, res->status);
|
||||
EXPECT_EQ(401, res->status);
|
||||
}
|
||||
|
||||
cli.set_digest_auth("bad", "world");
|
||||
for (auto path : paths) {
|
||||
auto res = cli.Get(path.c_str());
|
||||
ASSERT_TRUE(res != nullptr);
|
||||
EXPECT_EQ(400, res->status);
|
||||
}
|
||||
// NOTE: Until httpbin.org fixes issue #46, the following test is commented
|
||||
// out. Plese see https://httpbin.org/digest-auth/auth/hello/world
|
||||
// cli.set_digest_auth("bad", "world");
|
||||
// for (auto path : paths) {
|
||||
// auto res = cli.Get(path.c_str());
|
||||
// ASSERT_TRUE(res != nullptr);
|
||||
// EXPECT_EQ(401, res->status);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,66 +224,46 @@ void KeepAliveTest(Client& cli, bool basic) {
|
||||
#endif
|
||||
}
|
||||
|
||||
cli.set_keep_alive_max_count(4);
|
||||
cli.set_follow_location(true);
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
cli.set_digest_auth("hello", "world");
|
||||
#endif
|
||||
|
||||
std::vector<Request> requests;
|
||||
{
|
||||
auto res = cli.Get("/get");
|
||||
EXPECT_EQ(200, res->status);
|
||||
}
|
||||
{
|
||||
auto res = cli.Get("/redirect/2");
|
||||
EXPECT_EQ(200, res->status);
|
||||
}
|
||||
|
||||
Get(requests, "/get");
|
||||
Get(requests, "/redirect/2");
|
||||
{
|
||||
std::vector<std::string> paths = {
|
||||
"/digest-auth/auth/hello/world/MD5",
|
||||
"/digest-auth/auth/hello/world/SHA-256",
|
||||
"/digest-auth/auth/hello/world/SHA-512",
|
||||
"/digest-auth/auth-int/hello/world/MD5",
|
||||
};
|
||||
|
||||
std::vector<std::string> paths = {
|
||||
"/digest-auth/auth/hello/world/MD5",
|
||||
"/digest-auth/auth/hello/world/SHA-256",
|
||||
"/digest-auth/auth/hello/world/SHA-512",
|
||||
"/digest-auth/auth-int/hello/world/MD5",
|
||||
};
|
||||
|
||||
for (auto path : paths) {
|
||||
Get(requests, path.c_str());
|
||||
for (auto path: paths) {
|
||||
auto res = cli.Get(path.c_str());
|
||||
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res->body);
|
||||
EXPECT_EQ(200, res->status);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int count = 100;
|
||||
while (count--) {
|
||||
Get(requests, "/get");
|
||||
auto res = cli.Get("/get");
|
||||
EXPECT_EQ(200, res->status);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Response> responses;
|
||||
auto ret = cli.send(requests, responses);
|
||||
ASSERT_TRUE(ret == true);
|
||||
ASSERT_TRUE(requests.size() == responses.size());
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
{
|
||||
auto &res = responses[i++];
|
||||
EXPECT_EQ(200, res.status);
|
||||
}
|
||||
|
||||
{
|
||||
auto &res = responses[i++];
|
||||
EXPECT_EQ(200, res.status);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
int count = paths.size();
|
||||
while (count--) {
|
||||
auto &res = responses[i++];
|
||||
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n", res.body);
|
||||
EXPECT_EQ(200, res.status);
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < responses.size(); i++) {
|
||||
auto &res = responses[i];
|
||||
EXPECT_EQ(200, res.status);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
TEST(KeepAliveTest, NoSSLWithBasic) {
|
||||
Client cli("httpbin.org");
|
||||
KeepAliveTest(cli, true);
|
||||
@@ -290,7 +274,6 @@ TEST(KeepAliveTest, SSLWithBasic) {
|
||||
KeepAliveTest(cli, true);
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
TEST(KeepAliveTest, NoSSLWithDigest) {
|
||||
Client cli("httpbin.org");
|
||||
KeepAliveTest(cli, false);
|
||||
@@ -301,3 +284,4 @@ TEST(KeepAliveTest, SSLWithDigest) {
|
||||
KeepAliveTest(cli, false);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user