Compare commits

...

106 Commits

Author SHA1 Message Date
yhirose
71ba7e7b1b
Fix #2068 (#2080)
* Fix #2068

* Add unit test
2025-02-20 23:45:21 -05:00
Florian Albrechtskirchinger
ebe7efa1cc
Parallelize testing with/without SSL on Windows & set concurrency group (#2079)
* Parallelize testing with/without SSL on Windows

* Set concurrency group in workflows
2025-02-20 20:57:18 -05:00
Florian Albrechtskirchinger
22d90c29b4
Remove select() and use poll() (#2078)
* Revert "Fix typo in meson.build (#2070)"

This reverts commit 5c0135fa5d.

* Revert "build(meson): automatically use poll or select as needed (#2067)"

This reverts commit 2b5d1eea8d.

* Revert "Make poll() the default (#2065)"

This reverts commit 6e73a63153.

* Remove select() and use poll()
2025-02-20 18:51:35 -05:00
Florian Albrechtskirchinger
b944f942ee
Correct default thread pool size in README.md (#2077) 2025-02-20 12:59:38 -05:00
Florian Albrechtskirchinger
550f728165
Refactor streams: rename is_* to wait_* for clarity (#2069)
- Replace is_readable() with wait_readable() and is_writable() with
  wait_writable() in the Stream interface.
- Implement a new is_readable() function with semantics that more
  closely reflect its name. It returns immediately whether data is
  available for reading, without waiting.
- Update call sites of is_writable(), removing redundant checks.
2025-02-20 12:56:39 -05:00
yhirose
a4b2c61a65
Max timeout test refactoring (#2071)
* Simplify code

* Adjust threshold
2025-02-19 22:19:02 -05:00
Florian Albrechtskirchinger
5c0135fa5d
Fix typo in meson.build (#2070) 2025-02-19 16:20:44 -05:00
Andrea Pappacoda
2b5d1eea8d
build(meson): automatically use poll or select as needed (#2067)
Follow-up to 6e73a63153
2025-02-19 12:47:56 -05:00
yhirose
d274c0abe5 Fix typo 2025-02-18 21:33:32 -05:00
yhirose
dda2e007a0 Fixed documentation about Unix Domain Sockt (#2066) 2025-02-18 11:40:50 -05:00
yhirose
321a86d9f2 Add *.dSYM to Makefile clean 2025-02-18 05:56:22 -05:00
yhirose
ada97046a2 Fix misspelled words 2025-02-18 05:54:22 -05:00
Florian Albrechtskirchinger
6e73a63153
Make poll() the default (#2065)
* Make poll() the default

select() can still be enabled by defining CPPHTTPLIB_USE_SELECT.

* Run tests with select() and poll()
2025-02-18 05:23:23 -05:00
Uros Gaber
cdc223019a
server_certificate_verifier extended to reuse built-in verifier (#2064)
* server_certificate_verifier extended to reuse built-in verifier

* code cleanup and SSLVerifierResponse enum clarification as per @falbrechtskirchinger comment

* cleanup

* clang-format

* change local var verification_status_ declaration to auto

* change local var verification_status_ to verification_status

* clang-format

* clang-format

---------

Co-authored-by: UrosG <uros@ub330.net>
2025-02-17 17:24:41 -05:00
Florian Albrechtskirchinger
574f5ce93e
Add style check to workflow (#2062)
* Add style check to workflow

* Add example files to style check
2025-02-17 12:14:53 -05:00
Florian Albrechtskirchinger
2996cecee0
Fix code inconsistently formatted and re-format (#2063)
* Fix code inconsistently formatted by clang-format

* Run clang-format
2025-02-17 12:14:02 -05:00
Florian Albrechtskirchinger
32bf5c9c09
Simplify SSL shutdown (#2059) 2025-02-16 17:38:41 -05:00
Florian Albrechtskirchinger
735e5930eb
Detect additional CMake build failures (#2058)
Add include_httplib.cc to the main test executable (already done in
Makefile), and add include_windows_h.cc to the main test executable on
Windows to test if including windows.h conflicts with httplib.h.
2025-02-16 15:45:28 -05:00
Florian Albrechtskirchinger
748f47b377
Add workflow_dispatch with Google Test filter and OS selection (#2056)
* Add workflow_dispatch with Google Test filter

Add the workflow_dispatch trigger to the test.yaml workflow. Includes an
input for an optional Google Test filter pattern.

* Add OS selection to workflow_dispatch

* Fix wording
2025-02-16 12:34:28 -05:00
Florian Albrechtskirchinger
4cb8ff9f90
Print timeout exceedance in MaxTimeoutTest (#2060) 2025-02-16 08:43:54 -05:00
Florian Albrechtskirchinger
985cd9f6a2
Fix compilation failures with include <windows.h> (#2057) 2025-02-16 08:39:29 -05:00
Florian Albrechtskirchinger
233f0fb1b8
Refactor setting socket options (#2053)
Add detail::set_socket_opt() and detail::set_socket_opt_time() to avoid
repetition of platform-specific code.
2025-02-14 22:40:24 -05:00
yhirose
03cf43ebaa
Release v0.19.0 2025-02-14 14:42:29 -05:00
yhirose
3c4b96024f Don't run CI twice (on push AND pull request) 2025-02-14 14:19:54 -05:00
yhirose
d74e4a7c9c Removed incomplete API compatibility check scripts. 2025-02-14 14:10:06 -05:00
Andrea Pappacoda
bfa2f735f2
ci: add abidiff workflow (#2054)
This CI workflow checks ABI compatibility between the pushed commit and
the latest tagged release, helping preventing accidental ABI breaks.

Helps with https://github.com/yhirose/cpp-httplib/issues/2043
2025-02-14 14:06:35 -05:00
yhirose
b6ab8435d7 Improve ABI check tool on macOS 2025-02-12 12:49:20 -05:00
yhirose
39a64fb4e7 Fix ABI compatibility tool on macOS 2025-02-11 18:40:39 -05:00
yhirose
d7c14b6f3a Add API compatibility check tool 2025-02-11 17:49:33 -05:00
yhirose
1880693aef Dropped Visual Studio 2015 support 2025-02-11 11:22:46 -05:00
Florian Albrechtskirchinger
dd20342825
Don't run CI twice (on push AND pull request) (#2049) 2025-02-11 06:55:13 -05:00
Brett Profitt
a268d65c4f
Fix check for URI length to prevent incorrect HTTP 414 errors (#2046) 2025-02-10 21:46:38 -05:00
Florian Albrechtskirchinger
b397c768e4
Unify select_read() and select_write() (#2047) 2025-02-10 18:15:19 -05:00
yhirose
8e22a7676a Remome 'global timeout' to 'max timeout' 2025-02-10 18:07:30 -05:00
yhirose
8a7c536ad5
Fix #2034 (#2048)
* Fix #2034

* Fix build error

* Adjust threshold

* Add temporary debug prints

* Adjust threshhold

* Another threshold adjustment for macOS on GitHub Actions CI...

* Performance improvement by avoiding unnecessary chrono access

* More performance improvement to avoid unnecessary chrono access
2025-02-10 06:51:07 -05:00
yhirose
8aad481c69 Fix test.yaml problem 2025-02-08 23:37:41 -05:00
yhirose
5814e121df Release v0.18.7 2025-02-08 15:53:35 -05:00
Florian Albrechtskirchinger
7adbccbaf7
Refine when content is expected (#2044)
Consider Content-Length and Transfer-Encoding headers when determining
whether to expect content. Don't handle the HTTP/2 connection preface
pseudo-method PRI.

Fixes #2028.
2025-02-08 15:51:52 -05:00
yhirose
eb10c22db1 Add unit test for #609 2025-02-08 10:17:09 -05:00
yhirose
708f860e3a Fix #2042 2025-02-06 05:56:31 -05:00
yhirose
eb30f15363 Release v0.18.6 2025-02-05 19:14:20 -05:00
yhirose
4941d5b56b
Fix #2033 (#2039) 2025-02-05 12:46:33 -05:00
Florian Albrechtskirchinger
9bbb4741b4
Run clang-format (#2037) 2025-02-02 22:32:33 -05:00
yhirose
282f2feb77 Add a unit test 2025-02-01 22:11:15 -05:00
alex-cornford
60a1f00618
Support building httplib.h on OpenVMS x86 systems (#2031)
Modify for OpenVMS x86 C++. Make tests on OpenVMS currently not supported due to no cmake support.
Changes tested on OpenVMS clang C++ and Fedora & GCC
2025-01-28 18:44:22 -05:00
yhirose
9104054ca5 Fix README example 2025-01-27 13:37:16 -05:00
Baiyies
d69f144a99
Update httplib.h (#2030)
fix 'max'
2025-01-26 08:50:10 -05:00
yhirose
929dfbd348 Update copyright year 2025-01-20 00:32:10 -05:00
yhirose
3047183fd9 Update README 2025-01-20 00:02:02 -05:00
yhirose
ef5e4044f1 Update README 2025-01-19 23:46:12 -05:00
yhirose
3779800322 Release v0.18.5 2025-01-17 17:38:03 -05:00
yhirose
986a20fb7d
Resolve #2017 (#2022)
* Resolve #2017

* Fix warning

* Update README
2025-01-17 17:37:07 -05:00
yhirose
8311e1105f Fix Windows build problem 2025-01-16 23:26:04 -05:00
yhirose
ba6845925d Fix #2014 2025-01-16 23:10:58 -05:00
yhirose
343a0fc073 Fix #2011 2025-01-16 21:38:45 -05:00
yhirose
54f8a4d0f3 Release v0.18.4 2025-01-16 01:00:25 -05:00
yhirose
9c36aae4b7 Fix HTTP Response Splitting Vulnerability 2025-01-16 00:04:33 -05:00
yhirose
b766025a83 clangformat 2025-01-16 00:03:10 -05:00
yhirose
9b5f76f833 Fix #2012 2024-12-27 17:19:23 -05:00
sinnren
d647f484a4
fix:set_file_content with range request return 416. (#2010)
Co-authored-by: fenlog <bakurise@qq.com>
2024-12-24 09:38:59 -05:00
Sergey Bobrenok
8794792baa
Treat out-of-range last_pos as the end of the content (#2009)
RFC-9110 '14.1.2. Byte Ranges':
A client can limit the number of bytes requested without knowing the
size of the selected representation. If the last-pos value is absent,
or if the value is greater than or equal to the current length of the
representation data, the byte range is interpreted as the remainder of
the representation (i.e., the server replaces the value of last-pos
with a value that is one less than the current length of the selected
representation).

https://www.rfc-editor.org/rfc/rfc9110.html#section-14.1.2-6
2024-12-23 13:14:36 -05:00
yhirose
b85768c1f3 Fix #2005 2024-12-16 17:43:50 -05:00
yhirose
e6d71bd702 Add a unit test for Issue #2004 2024-12-12 18:15:22 -05:00
yhirose
258992a160 Changed to use non-blocking socket in is_ssl_peer_could_be_closed 2024-12-03 19:26:08 -05:00
yhirose
a7bc00e330 Release v0.18.3 2024-12-03 06:33:00 -05:00
yhirose
11a40584e9 Fix #1998 2024-12-03 00:38:20 -05:00
yhirose
3e86bdb4d8
Fix #1997 (#2001) 2024-12-03 00:11:29 -05:00
Pavel P
c817d65695
Fix casting uint64_t to size_t for 32-bit builds (#1999) 2024-12-02 11:09:52 -05:00
yhirose
51dee793fe Release v0.18.2 2024-11-29 20:49:50 -05:00
yhirose
457fc4306e Fix #1993 2024-11-29 20:46:48 -05:00
yhirose
4f5b003e76 Fix #1992 2024-11-28 20:40:38 -05:00
yhirose
5421e27106 Fix a compiler warning 2024-11-28 20:39:26 -05:00
yhirose
fe07660f40
Fix #1986 (#1988) 2024-11-27 12:18:35 -05:00
yhirose
da2f9e476e
Fix #1985 (#1989) 2024-11-27 12:18:23 -05:00
sebastianas
1a7a7ed1c3
test: Don't check for the exact size of compressed content. (#1984)
The testsuite checks for the exact size of the compressed content. The
exact size can change if the zlib library is using a different strategy.
In thise case using zlib-ng results in a slightly larger content leading
to a failure in the test.

Check that the compressed content is less than 10MiB which is a tenth of
the orignal content and proves that compression works.

Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
2024-11-25 15:46:41 -05:00
yhirose
413994912d Update vcxproj files 2024-11-16 11:14:13 -05:00
yhirose
01dcf1d0ad
Fix #1969 (without unnecessary sleep_for) (#1982) 2024-11-16 10:56:57 -05:00
yhirose
8e378779c2 Update README 2024-11-16 09:45:04 -05:00
yhirose
970b52897c
Fix #1980
Fix #1980
2024-11-16 02:09:52 -05:00
yhirose
412ba04d19 Fix problem caused by #1975 2024-11-14 20:33:08 -05:00
yhirose
bfef4b3e9b Fix #1975 2024-11-14 17:27:28 -05:00
yhirose
7bd316f3d0 Fix #1977 2024-11-14 16:46:27 -05:00
yhirose
26208363ee Fix warning 2024-11-14 16:46:09 -05:00
yhirose
b1b4bb8850 clangformat 2024-11-13 22:50:03 -05:00
yhirose
9dd565b6e3
Resolve #1973 (#1976)
* Fix #1973

* Fixed problems with 'Language for non-Unicode programs' setting on Windows

* Fix problems on English locale
2024-11-13 22:47:09 -05:00
yhirose
924f214303 Added unit test for exception handler 2024-11-02 07:23:44 -04:00
yhirose
5c1a34e766 Release v0.18.1 2024-10-18 17:16:54 -04:00
yhirose
fa90d06dd5 Merge branch 'master' of github.com:yhirose/cpp-httplib 2024-10-18 17:16:14 -04:00
Jiwoo Park
d869054318
Allow empty header values (#1965) 2024-10-18 10:16:48 -04:00
Peter Boström
0cc1ca9a8d
Remove extra semicolon (#1963)
This fixes a -Wc++98-compat-extra-semi instance.
2024-10-15 00:09:04 -04:00
yhirose
3701195033 Merge branch 'master' of github.com:yhirose/cpp-httplib 2024-10-14 21:32:28 -04:00
Peter Boström
f884a56258
Remove space between operator"" and _t (#1962)
This should fix a -Wdeprecated-literal-operator instance since this is
deprecated as a result of CWG2521 (iiuc C++23).
2024-10-14 21:32:13 -04:00
yhirose
d79633ff52 clangformat 2024-10-11 14:49:46 -04:00
yhirose
e0ebc431dc Fix #1959 2024-10-11 13:43:01 -04:00
Andrew McDaniel
131bc6c674
Add documentation for using Unix domain sockets. (#1954)
* Add documentation for using unix domain sockets.

* Formatting
2024-10-03 10:53:25 -04:00
yhirose
10d68cff50 Added a unit test for #1946 2024-09-26 22:24:44 -04:00
zjyhjqs
996acc5253
Feat: add CPack support (#1950) 2024-09-25 00:19:41 -04:00
yhirose
7c4799d0cf
Fix #1798 for CMake (#1944) 2024-09-19 18:33:32 -04:00
yhirose
c239087332 Fix Mafile errors 2024-09-17 18:37:44 -04:00
Andrea Pappacoda
7018e9263d
test(meson): copy files in www directory (#1941)
These files were added in commits
2d01e71286 and
b8315278cb
2024-09-17 18:06:01 -04:00
yhirose
4990b4b4b7 Fix problems with SSLSlientServerTest.* tests 2024-09-17 17:00:17 -04:00
Andrea Pappacoda
5064373c23
test(meson): fix SSLClientServerTest.* tests with OpenSSL 3.2.0 (#1940)
* build(meson): bump minimum version to 0.62.0

This allows making some minor cleanups

* test(meson): fix SSLClientServerTest.* tests with OpenSSL 3.2.0

Since OpenSSL commit
<342e3652c7>,
the default X.509 certificate format generated with the `openssl req`
command has been changed to X.509 v3 from X.509 v1.

For some reason, this change breaks cpp-httplib's SSLClientServerTest.*
tests.

To fix the test failures, this patch passes the '-x509v1' flag instead
of '-x509' when OpenSSL 3.2.0 or newer is detected. To detect the
version of a command line utility, Meson 0.62.0 or later is required.

Fixes <https://github.com/yhirose/cpp-httplib/issues/1798>, but only for
the Meson build system.
2024-09-17 16:58:09 -04:00
yhirose
6c93aea59a Revert "Enabled HostnameToIPConversionTest.YouTube_Online partially"
This reverts commit 6553cdedab.
2024-09-15 01:18:20 -04:00
yhirose
6553cdedab Enabled HostnameToIPConversionTest.YouTube_Online partially 2024-09-13 20:45:59 -04:00
yhirose
a61b2427b0 Update benchmark base vertion to 0.18.0 2024-09-13 20:34:30 -04:00
yhirose
af4ece3d5f Update benchmark/Makefile 2024-09-12 20:41:56 -04:00
29 changed files with 2243 additions and 886 deletions

69
.github/workflows/abidiff.yaml vendored Normal file
View File

@ -0,0 +1,69 @@
# SPDX-FileCopyrightText: 2025 Andrea Pappacoda <andrea@pappacoda.it>
# SPDX-License-Identifier: MIT
name: abidiff
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true
defaults:
run:
shell: sh
jobs:
abi:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
container:
image: debian:testing
steps:
- name: Install dependencies
run: apt -y --update install --no-install-recommends
abigail-tools
ca-certificates
g++
git
libbrotli-dev
libssl-dev
meson
pkg-config
python3
zlib1g-dev
- uses: actions/checkout@v4
with:
path: current
- uses: actions/checkout@v4
with:
path: previous
fetch-depth: 0
- name: Checkout previous
working-directory: previous
run: |
git switch master
git describe --tags --abbrev=0 master | xargs git checkout
- name: Build current
working-directory: current
run: |
meson setup --buildtype=debug -Dcpp-httplib_compile=true build
ninja -C build
- name: Build previous
working-directory: previous
run: |
meson setup --buildtype=debug -Dcpp-httplib_compile=true build
ninja -C build
- name: Run abidiff
run: abidiff
--headers-dir1 previous/build
--headers-dir2 current/build
previous/build/libcpp-httplib.so
current/build/libcpp-httplib.so

View File

@ -1,5 +1,11 @@
name: CIFuzz
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true
jobs:
Fuzzing:
runs-on: ubuntu-latest

View File

@ -1,43 +1,126 @@
name: test
on: [push, pull_request]
on:
push:
pull_request:
workflow_dispatch:
inputs:
gtest_filter:
description: 'Google Test filter'
test_linux:
description: 'Test on Linux'
type: boolean
default: true
test_macos:
description: 'Test on MacOS'
type: boolean
default: true
test_windows:
description: 'Test on Windows'
type: boolean
default: true
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true
env:
GTEST_FILTER: ${{ github.event.inputs.gtest_filter || '*' }}
jobs:
style-check:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
continue-on-error: true
steps:
- name: checkout
uses: actions/checkout@v4
- name: run style check
run: |
clang-format --version
cd test && make style_check
ubuntu:
runs-on: ubuntu-latest
if: >
(github.event_name == 'push') ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
steps:
- name: checkout
uses: actions/checkout@v4
- name: install libraries
run: sudo apt-get update && sudo apt-get install -y libbrotli-dev libcurl4-openssl-dev
- name: build and run tests
run: cd test && make -j4
run: cd test && make
- name: run fuzz test target
run: cd test && make fuzz_test
macos:
runs-on: macos-latest
if: >
(github.event_name == 'push') ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_macos == 'true')
steps:
- name: checkout
uses: actions/checkout@v4
- name: build and run tests
run: |
cd test && make -j2
run: cd test && make
- name: run fuzz test target
run: cd test && make fuzz_test
windows:
runs-on: windows-latest
if: >
(github.event_name == 'push') ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_windows == 'true')
strategy:
matrix:
config:
- with_ssl: false
name: without SSL
- with_ssl: true
name: with SSL
name: windows ${{ matrix.config.name }}
steps:
- name: prepare git for checkout on windows
- name: Prepare Git for Checkout on Windows
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: checkout
- name: Checkout
uses: actions/checkout@v4
- name: setup msbuild on windows
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Setup msbuild on windows
uses: microsoft/setup-msbuild@v2
- name: make-windows
run: |
cd test
msbuild.exe test.sln /verbosity:minimal /t:Build "/p:Configuration=Release;Platform=x64"
x64\Release\test.exe
- name: Install vcpkg dependencies
run: vcpkg install gtest curl zlib brotli
- name: Install OpenSSL
if: ${{ matrix.config.with_ssl }}
run: choco install openssl
- name: Configure CMake ${{ matrix.config.name }}
run: >
cmake -B build -S .
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
-DHTTPLIB_TEST=ON
-DHTTPLIB_REQUIRE_ZLIB=ON
-DHTTPLIB_REQUIRE_BROTLI=ON
-DHTTPLIB_REQUIRE_OPENSSL=${{ matrix.config.with_ssl && 'ON' || 'OFF' }}
- name: Build ${{ matrix.config.name }}
run: cmake --build build --config Release -- /v:m /clp:ShowCommandLine
- name: Run tests ${{ matrix.config.name }}
run: ctest --output-on-failure --test-dir build -C Release
env:
VCPKG_ROOT: "C:/vcpkg"
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"

1
.gitignore vendored
View File

@ -23,6 +23,7 @@ test/test.xcodeproj/*/xcuser*
test/*.o
test/*.pem
test/*.srl
test/_build_*
work/
benchmark/server*

View File

@ -299,6 +299,8 @@ if(HTTPLIB_INSTALL)
# ex: /usr/share/doc/httplib/README.md and /usr/share/licenses/httplib/LICENSE
install(FILES "README.md" DESTINATION "${CMAKE_INSTALL_DOCDIR}")
install(FILES "LICENSE" DESTINATION "${CMAKE_INSTALL_DATADIR}/licenses/${PROJECT_NAME}")
include(CPack)
endif()
if(HTTPLIB_TEST)

View File

@ -2,7 +2,7 @@ FROM yhirose4dockerhub/ubuntu-builder AS builder
WORKDIR /build
COPY httplib.h .
COPY docker/main.cc .
RUN g++ -std=c++23 -static -o server -O2 -I. -DCPPHTTPLIB_USE_POLL main.cc && strip server
RUN g++ -std=c++23 -static -o server -O2 -I. main.cc && strip server
FROM scratch
COPY --from=builder /build/server /server

View File

@ -39,10 +39,10 @@ svr.listen("0.0.0.0", 8080);
#include "path/to/httplib.h"
// HTTP
httplib::Client cli("http://cpp-httplib-server.yhirose.repl.co");
httplib::Client cli("http://yhirose.github.io");
// HTTPS
httplib::Client cli("https://cpp-httplib-server.yhirose.repl.co");
httplib::Client cli("https://yhirose.github.io");
auto res = cli.Get("/hi");
res->status;
@ -79,7 +79,7 @@ cli.set_ca_cert_path("./ca-bundle.crt");
cli.enable_server_certificate_verification(false);
// Disable host verification
cli.enable_server_host_verification(false);
cli.enable_server_hostname_verification(false);
```
> [!NOTE]
@ -125,6 +125,21 @@ int main(void)
res.set_content(req.body, "text/plain");
});
// If the handler takes time to finish, you can also poll the connection state
svr.Get("/task", [&](const Request& req, Response& res) {
const char * result = nullptr;
process.run(); // for example, starting an external process
while (result == nullptr) {
sleep(1);
if (req.is_connection_closed()) {
process.kill(); // kill the process
return;
}
result = process.stdout(); // != nullptr if the process finishes
}
res.set_content(result, "text/plain");
});
svr.Get("/stop", [&](const Request& req, Response& res) {
svr.stop();
});
@ -391,11 +406,11 @@ svr.Get("/chunked", [&](const Request& req, Response& res) {
```cpp
svr.Get("/content", [&](const Request &req, Response &res) {
res.set_file_content("./path/to/conent.html");
res.set_file_content("./path/to/content.html");
});
svr.Get("/content", [&](const Request &req, Response &res) {
res.set_file_content("./path/to/conent", "text/html");
res.set_file_content("./path/to/content", "text/html");
});
```
@ -447,7 +462,7 @@ Please see [Server example](https://github.com/yhirose/cpp-httplib/blob/master/e
### Default thread pool support
`ThreadPool` is used as a **default** task queue, and the default thread count is 8, or `std::thread::hardware_concurrency()`. You can change it with `CPPHTTPLIB_THREAD_POOL_COUNT`.
`ThreadPool` is used as the **default** task queue, with a default thread count of 8 or `std::thread::hardware_concurrency() - 1`, whichever is greater. You can change it with `CPPHTTPLIB_THREAD_POOL_COUNT`.
If you want to set the thread count at runtime, there is no convenient way... But here is how.
@ -557,18 +572,18 @@ enum Error {
```c++
httplib::Headers headers = {
{ "Accept-Encoding", "gzip, deflate" }
{ "Hello", "World!" }
};
auto res = cli.Get("/hi", headers);
```
or
```c++
auto res = cli.Get("/hi", {{"Accept-Encoding", "gzip, deflate"}});
auto res = cli.Get("/hi", {{"Hello", "World!"}});
```
or
```c++
cli.set_default_headers({
{ "Accept-Encoding", "gzip, deflate" }
{ "Hello", "World!" }
});
auto res = cli.Get("/hi");
```
@ -639,6 +654,9 @@ res = cli.Options("/resource/foo");
cli.set_connection_timeout(0, 300000); // 300 milliseconds
cli.set_read_timeout(5, 0); // 5 seconds
cli.set_write_timeout(5, 0); // 5 seconds
// This method works the same as curl's `--max-timeout` option
svr.set_max_timeout(5000); // 5 seconds
```
### Receive content with a content receiver
@ -823,6 +841,21 @@ The server can apply compression to the following MIME type contents:
Brotli compression is available with `CPPHTTPLIB_BROTLI_SUPPORT`. Necessary libraries should be linked.
Please see https://github.com/google/brotli for more detail.
### Default `Accept-Encoding` value
The default `Accept-Encoding` value contains all possible compression types. So, the following two examples are same.
```c++
res = cli.Get("/resource/foo");
res = cli.Get("/resource/foo", {{"Accept-Encoding", "gzip, deflate, br"}});
```
If we don't want a response without compression, we have to set `Accept-Encoding` to an empty string. This behavior is similar to curl.
```c++
res = cli.Get("/resource/foo", {{"Accept-Encoding", ""}});
```
### Compress request body on client
```c++
@ -834,14 +867,27 @@ res = cli.Post("/resource/foo", "...", "text/plain");
```c++
cli.set_decompress(false);
res = cli.Get("/resource/foo", {{"Accept-Encoding", "gzip, deflate, br"}});
res = cli.Get("/resource/foo");
res->body; // Compressed data
```
Use `poll` instead of `select`
------------------------------
Unix Domain Socket Support
--------------------------
`select` system call is used as default since it's more widely supported. If you want to let cpp-httplib use `poll` instead, you can do so with `CPPHTTPLIB_USE_POLL`.
Unix Domain Socket support is available on Linux and macOS.
```c++
// Server
httplib::Server svr;
svr.set_address_family(AF_UNIX).listen("./my-socket.sock", 80);
// Client
httplib::Client cli("./my-socket.sock");
cli.set_address_family(AF_UNIX);
```
"my-socket.sock" can be a relative path or an absolute path. You application must have the appropriate permissions for the path. You can also use an abstract socket address on Linux. To use an abstract socket address, prepend a null byte ('\x00') to the path.
Split httplib.h into .h and .cc
@ -883,9 +929,6 @@ From Docker Hub
```bash
> docker run --rm -it -p 8080:80 -v ./docker/html:/html yhirose4dockerhub/cpp-httplib-server
...
> docker run --init --rm -it -p 8080:80 -v ./docker/html:/html cpp-httplib-server
Serving HTTP on 0.0.0.0 port 80 ...
192.168.65.1 - - [31/Aug/2024:21:33:56 +0000] "GET / HTTP/1.1" 200 599 "-" "curl/8.7.1"
192.168.65.1 - - [31/Aug/2024:21:34:26 +0000] "GET / HTTP/1.1" 200 599 "-" "Mozilla/5.0 ..."
@ -918,12 +961,12 @@ Include `httplib.h` before `Windows.h` or include `Windows.h` by defining `WIN32
> 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 and MSYS2 including MinGW are neither supported nor tested.
> Windows 8 or lower, Visual Studio 2015 or lower, and Cygwin and MSYS2 including MinGW are neither supported nor tested.
License
-------
MIT license (© 2024 Yuji Hirose)
MIT license (© 2025 Yuji Hirose)
Special Thanks To
-----------------

View File

@ -1,6 +1,6 @@
CXXFLAGS = -std=c++11 -O2 -I..
THEAD_POOL_COUNT = 16
CPPHTTPLIB_FLAGS = -DCPPHTTPLIB_THREAD_POOL_COUNT=16
BENCH = bombardier -c 10 -d 5s localhost:8080
MONITOR = ali http://localhost:8080
@ -18,11 +18,11 @@ run : server
@./server
server : cpp-httplib/main.cpp ../httplib.h
g++ -o $@ $(CXXFLAGS) -DCPPHTTPLIB_THREAD_POOL_COUNT=$(THEAD_POOL_COUNT) cpp-httplib/main.cpp
g++ -o $@ $(CXXFLAGS) $(CPPHTTPLIB_FLAGS) cpp-httplib/main.cpp
# cpp-httplib
bench-base: server-base
@echo "---------------------\n cpp-httplib v0.17.0\n---------------------\n"
@echo "---------------------\n cpp-httplib v0.18.0\n---------------------\n"
@./server-base & export PID=$$!; $(BENCH); kill $${PID}
@echo ""
@ -33,7 +33,7 @@ run-base : server-base
@./server-base
server-base : cpp-httplib-base/main.cpp cpp-httplib-base/httplib.h
g++ -o $@ $(CXXFLAGS) -DCPPHTTPLIB_THREAD_POOL_COUNT=$(THEAD_POOL_COUNT) cpp-httplib-base/main.cpp
g++ -o $@ $(CXXFLAGS) $(CPPHTTPLIB_FLAGS) cpp-httplib-base/main.cpp
# crow
bench-crow: server-crow
@ -51,10 +51,12 @@ server-crow : crow/main.cpp
g++ -o $@ $(CXXFLAGS) crow/main.cpp
# misc
build: server server-base server-crow
bench-all: bench-crow bench bench-base
issue:
$(BENCH)
bombardier -c 10 -d 30s localhost:8080
clean:
rm -rf server*

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
//
// main.cc
//
// Copyright (c) 2024 Yuji Hirose. All rights reserved.
// Copyright (c) 2025 Yuji Hirose. All rights reserved.
// MIT License
//
@ -41,7 +41,7 @@ std::string log(auto &req, auto &res) {
auto http_referer = "-"; // TODO:
auto http_user_agent = req.get_header_value("User-Agent", "-");
// NOTE: From NGINX defualt access log format
// NOTE: From NGINX default access log format
// log_format combined '$remote_addr - $remote_user [$time_local] '
// '"$request" $status $body_bytes_sent '
// '"$http_referer" "$http_user_agent"';

View File

@ -18,7 +18,7 @@ ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
BROTLI_DIR = $(PREFIX)/opt/brotli
BROTLI_SUPPORT = -DCPPHTTPLIB_BROTLI_SUPPORT -I$(BROTLI_DIR)/include -L$(BROTLI_DIR)/lib -lbrotlicommon -lbrotlienc -lbrotlidec
all: server client hello simplecli simplesvr upload redirect ssesvr ssecli benchmark issue
all: server client hello simplecli simplesvr upload redirect ssesvr ssecli benchmark one_time_request server_and_client
server : server.cc ../httplib.h Makefile
$(CXX) -o server $(CXXFLAGS) server.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT) $(BROTLI_SUPPORT)

View File

@ -22,34 +22,34 @@
<ProjectGuid>{6DB1FC63-B153-4279-92B7-D8A11AF285D6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>client</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">

View File

@ -18,38 +18,41 @@
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="simplesvr.cc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{864CD288-050A-4C8B-9BEF-3048BD876C5B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>sample</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -151,9 +154,6 @@
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="server.cc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -1,7 +1,7 @@
//
// server_and_client.cc
//
// Copyright (c) 2024 Yuji Hirose. All rights reserved.
// Copyright (c) 2025 Yuji Hirose. All rights reserved.
// MIT License
//

View File

@ -12,8 +12,7 @@ using namespace std;
class EventDispatcher {
public:
EventDispatcher() {
}
EventDispatcher() {}
void wait_event(DataSink *sink) {
unique_lock<mutex> lk(m_);

1183
httplib.h

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ project(
'b_lto=true',
'warning_level=3'
],
meson_version: '>=0.47.0'
meson_version: '>=0.62.0'
)
# Check just in case downstream decides to edit the source
@ -98,20 +98,18 @@ if get_option('cpp-httplib_compile')
)
else
install_headers('httplib.h')
cpp_httplib_dep = declare_dependency(compile_args: args, dependencies: deps, include_directories: include_directories('.'))
cpp_httplib_dep = declare_dependency(compile_args: args, dependencies: deps, include_directories: '.')
import('pkgconfig').generate(
name: 'cpp-httplib',
description: 'A C++ HTTP/HTTPS server and client library',
install_dir: join_paths(get_option('datadir'), 'pkgconfig'),
install_dir: get_option('datadir')/'pkgconfig',
url: 'https://github.com/yhirose/cpp-httplib',
version: version
)
endif
if meson.version().version_compare('>=0.54.0')
meson.override_dependency('cpp-httplib', cpp_httplib_dep)
endif
meson.override_dependency('cpp-httplib', cpp_httplib_dep)
if get_option('cpp-httplib_test')
subdir('test')

View File

@ -26,7 +26,7 @@ endif()
find_package(CURL REQUIRED)
add_executable(httplib-test test.cc)
add_executable(httplib-test test.cc include_httplib.cc $<$<BOOL:${WIN32}>:include_windows_h.cc>)
target_compile_options(httplib-test PRIVATE "$<$<CXX_COMPILER_ID:MSVC>:/utf-8;/bigobj>")
target_link_libraries(httplib-test PRIVATE httplib GTest::gtest_main CURL::libcurl)
gtest_discover_tests(httplib-test)
@ -37,6 +37,11 @@ file(
)
if(HTTPLIB_IS_USING_OPENSSL)
if (OPENSSL_VERSION VERSION_LESS "3.2.0")
set(OPENSSL_X509_FLAG "-x509")
else()
set(OPENSSL_X509_FLAG "-x509v1")
endif()
find_program(OPENSSL_COMMAND
NAMES openssl
PATHS ${OPENSSL_INCLUDE_DIR}/../bin
@ -56,7 +61,7 @@ if(HTTPLIB_IS_USING_OPENSSL)
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND ${OPENSSL_COMMAND} req -x509 -new -config ${CMAKE_CURRENT_LIST_DIR}/test.conf -key key.pem -sha256 -days 3650 -nodes -out cert2.pem -extensions SAN
COMMAND ${OPENSSL_COMMAND} req ${OPENSSL_X509_FLAG} -new -config ${CMAKE_CURRENT_LIST_DIR}/test.conf -key key.pem -sha256 -days 3650 -nodes -out cert2.pem -extensions SAN
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND_ERROR_IS_FATAL ANY
)
@ -67,7 +72,7 @@ if(HTTPLIB_IS_USING_OPENSSL)
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND ${OPENSSL_COMMAND} req -x509 -new -batch -config ${CMAKE_CURRENT_LIST_DIR}/test.rootCA.conf -key rootCA.key.pem -days 1024
COMMAND ${OPENSSL_COMMAND} req ${OPENSSL_X509_FLAG} -new -batch -config ${CMAKE_CURRENT_LIST_DIR}/test.rootCA.conf -key rootCA.key.pem -days 1024
OUTPUT_FILE rootCA.cert.pem
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND_ERROR_IS_FATAL ANY

View File

@ -28,6 +28,11 @@ TEST_ARGS = gtest/gtest-all.cc gtest/gtest_main.cc $(OPENSSL_SUPPORT) $(ZLIB_SUP
# OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE.
LIB_FUZZING_ENGINE ?= standalone_fuzz_target_runner.o
CLANG_FORMAT = clang-format
REALPATH = $(shell which grealpath 2>/dev/null || which realpath 2>/dev/null)
STYLE_CHECK_FILES = $(filter-out httplib.h httplib.cc, \
$(wildcard example/*.h example/*.cc fuzzing/*.h fuzzing/*.cc *.h *.cc ../httplib.h))
all : test test_split
./test
@ -42,6 +47,31 @@ test : test.cc include_httplib.cc ../httplib.h Makefile cert.pem
test_split : test.cc ../httplib.h httplib.cc Makefile cert.pem
$(CXX) -o $@ $(CXXFLAGS) test.cc httplib.cc $(TEST_ARGS)
check_abi:
@./check-shared-library-abi-compatibility.sh
.PHONY: style_check
style_check: $(STYLE_CHECK_FILES)
@for file in $(STYLE_CHECK_FILES); do \
$(CLANG_FORMAT) $$file > $$file.formatted; \
if ! diff -u $$file $$file.formatted; then \
file2=$$($(REALPATH) --relative-to=.. $$file); \
printf "\n%*s\n" 80 | tr ' ' '#'; \
printf "##%*s##\n" 76; \
printf "## %-70s ##\n" "$$file2 not properly formatted. Please run clang-format."; \
printf "##%*s##\n" 76; \
printf "%*s\n\n" 80 | tr ' ' '#'; \
failed=1; \
fi; \
rm -f $$file.formatted; \
done; \
if [ -n "$$failed" ]; then \
echo "Style check failed for one or more files. See above for details."; \
false; \
else \
echo "All files are properly formatted."; \
fi
test_proxy : test_proxy.cc ../httplib.h Makefile cert.pem
$(CXX) -o $@ -I.. $(CXXFLAGS) test_proxy.cc $(TEST_ARGS)
@ -63,18 +93,8 @@ httplib.cc : ../httplib.h
python3 ../split.py -o .
cert.pem:
openssl genrsa 2048 > key.pem
openssl req -new -batch -config test.conf -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem
openssl req -x509 -config test.conf -key key.pem -sha256 -days 3650 -nodes -out cert2.pem -extensions SAN
openssl genrsa 2048 > rootCA.key.pem
openssl req -x509 -new -batch -config test.rootCA.conf -key rootCA.key.pem -days 1024 > rootCA.cert.pem
openssl genrsa 2048 > client.key.pem
openssl req -new -batch -config test.conf -key client.key.pem | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client.cert.pem
openssl genrsa -passout pass:test123! 2048 > key_encrypted.pem
openssl req -new -batch -config test.conf -key key_encrypted.pem | openssl x509 -days 3650 -req -signkey key_encrypted.pem > cert_encrypted.pem
openssl genrsa -aes256 -passout pass:test012! 2048 > client_encrypted.key.pem
openssl req -new -batch -config test.conf -key client_encrypted.key.pem -passin pass:test012! | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client_encrypted.cert.pem
#c_rehash .
./gen-certs.sh
clean:
rm -f test test_split test_proxy server_fuzzer *.pem *.0 *.o *.1 *.srl httplib.h httplib.cc
rm -rf test test_split test_proxy server_fuzzer *.pem *.0 *.o *.1 *.srl httplib.h httplib.cc _build* *.dSYM

View File

@ -25,7 +25,9 @@ public:
bool is_readable() const override { return true; }
bool is_writable() const override { return true; }
bool wait_readable() const override { return true; }
bool wait_writable() const override { return true; }
void get_remote_ip_and_port(std::string &ip, int &port) const override {
ip = "127.0.0.1";
@ -39,6 +41,8 @@ public:
socket_t socket() const override { return 0; }
time_t duration() const override { return 0; };
private:
const uint8_t *data_;
size_t size_;

18
test/gen-certs.sh Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
if [[ $(openssl version) =~ 3\.[2-9]\.[0-9]+ ]]; then
OPENSSL_X509_FLAG='-x509v1'
else
OPENSSL_X509_FLAG='-x509'
fi
openssl genrsa 2048 > key.pem
openssl req -new -batch -config test.conf -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem
openssl req -x509 -config test.conf -key key.pem -sha256 -days 3650 -nodes -out cert2.pem -extensions SAN
openssl genrsa 2048 > rootCA.key.pem
openssl req $OPENSSL_X509_FLAG -new -batch -config test.rootCA.conf -key rootCA.key.pem -days 1024 > rootCA.cert.pem
openssl genrsa 2048 > client.key.pem
openssl req -new -batch -config test.conf -key client.key.pem | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client.cert.pem
openssl genrsa -passout pass:test123! 2048 > key_encrypted.pem
openssl req -new -batch -config test.conf -key key_encrypted.pem | openssl x509 -days 3650 -req -signkey key_encrypted.pem > cert_encrypted.pem
openssl genrsa -aes256 -passout pass:test012! 2048 > client_encrypted.key.pem
openssl req -new -batch -config test.conf -key client_encrypted.key.pem -passin pass:test012! | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client_encrypted.cert.pem

View File

@ -0,0 +1,6 @@
// Test if including windows.h conflicts with httplib.h
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <httplib.h>

28
test/make-shared-library.sh Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
if [ "$#" -ne 1 ]; then
echo "Usage: $0 build_dir"
exit 1
fi
BUILD_DIR=$1
# Make the build directory
rm -rf $BUILD_DIR
mkdir -p $BUILD_DIR/out
cd $BUILD_DIR
# Build the version
git checkout $BUILD_DIR -q
cmake \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-g -Og" \
-DBUILD_SHARED_LIBS=ON \
-DHTTPLIB_COMPILE=ON \
-DCMAKE_INSTALL_PREFIX=./out \
../..
cmake --build . --target install
cmake --build . --target clean

View File

@ -6,6 +6,7 @@ gtest_dep = dependency('gtest', main: true)
libcurl_dep = dependency('libcurl')
openssl = find_program('openssl')
test_conf = files('test.conf')
req_x509_flag = openssl.version().version_compare('>=3.2.0') ? '-x509v1' : '-x509'
key_pem = custom_target(
'key_pem',
@ -31,7 +32,7 @@ cert2_pem = custom_target(
'cert2_pem',
input: key_pem,
output: 'cert2.pem',
command: [openssl, 'req', '-x509', '-config', test_conf, '-key', '@INPUT@', '-sha256', '-days', '3650', '-nodes', '-out', '@OUTPUT@', '-extensions', 'SAN']
command: [openssl, 'req', req_x509_flag, '-config', test_conf, '-key', '@INPUT@', '-sha256', '-days', '3650', '-nodes', '-out', '@OUTPUT@', '-extensions', 'SAN']
)
key_encrypted_pem = custom_target(
@ -44,7 +45,7 @@ cert_encrypted_pem = custom_target(
'cert_encrypted_pem',
input: key_encrypted_pem,
output: 'cert_encrypted.pem',
command: [openssl, 'req', '-x509', '-config', test_conf, '-key', '@INPUT@', '-sha256', '-days', '3650', '-nodes', '-out', '@OUTPUT@', '-extensions', 'SAN']
command: [openssl, 'req', req_x509_flag, '-config', test_conf, '-key', '@INPUT@', '-sha256', '-days', '3650', '-nodes', '-out', '@OUTPUT@', '-extensions', 'SAN']
)
rootca_key_pem = custom_target(
@ -57,7 +58,7 @@ rootca_cert_pem = custom_target(
'rootca_cert_pem',
input: rootca_key_pem,
output: 'rootCA.cert.pem',
command: [openssl, 'req', '-x509', '-new', '-batch', '-config', files('test.rootCA.conf'), '-key', '@INPUT@', '-days', '1024', '-out', '@OUTPUT@']
command: [openssl, 'req', req_x509_flag, '-new', '-batch', '-config', files('test.rootCA.conf'), '-key', '@INPUT@', '-days', '1024', '-out', '@OUTPUT@']
)
client_key_pem = custom_target(
@ -103,9 +104,9 @@ client_encrypted_cert_pem = custom_target(
# Copy test files to the build directory
configure_file(input: 'ca-bundle.crt', output: 'ca-bundle.crt', copy: true)
configure_file(input: 'image.jpg', output: 'image.jpg', copy: true)
subdir(join_paths('www', 'dir'))
subdir(join_paths('www2', 'dir'))
subdir(join_paths('www3', 'dir'))
subdir('www')
subdir('www2'/'dir')
subdir('www3'/'dir')
# GoogleTest 1.13.0 requires C++14
test_options = []

File diff suppressed because it is too large Load Diff

View File

@ -28,26 +28,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
@ -177,4 +177,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -5,8 +5,7 @@
using namespace std;
using namespace httplib;
template <typename T>
void ProxyTest(T& cli, bool basic) {
template <typename T> void ProxyTest(T &cli, bool basic) {
cli.set_proxy("localhost", basic ? 3128 : 3129);
auto res = cli.Get("/httpbin/get");
ASSERT_TRUE(res != nullptr);
@ -38,7 +37,7 @@ TEST(ProxyTest, SSLDigest) {
// ----------------------------------------------------------------------------
template <typename T>
void RedirectProxyText(T& cli, const char *path, bool basic) {
void RedirectProxyText(T &cli, const char *path, bool basic) {
cli.set_proxy("localhost", basic ? 3128 : 3129);
if (basic) {
cli.set_proxy_basic_auth("hello", "world");
@ -100,8 +99,7 @@ TEST(RedirectTest, YouTubeSSLDigest) {
// ----------------------------------------------------------------------------
template <typename T>
void BaseAuthTestFromHTTPWatch(T& cli) {
template <typename T> void BaseAuthTestFromHTTPWatch(T &cli) {
cli.set_proxy("localhost", 3128);
cli.set_proxy_basic_auth("hello", "world");
@ -112,11 +110,11 @@ void BaseAuthTestFromHTTPWatch(T& cli) {
}
{
auto res =
cli.Get("/basic-auth/hello/world",
{make_basic_authentication_header("hello", "world")});
auto res = cli.Get("/basic-auth/hello/world",
{make_basic_authentication_header("hello", "world")});
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(StatusCode::OK_200, res->status);
}
@ -124,7 +122,8 @@ void BaseAuthTestFromHTTPWatch(T& cli) {
cli.set_basic_auth("hello", "world");
auto res = cli.Get("/basic-auth/hello/world");
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(StatusCode::OK_200, res->status);
}
@ -158,8 +157,7 @@ TEST(BaseAuthTest, SSL) {
// ----------------------------------------------------------------------------
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
template <typename T>
void DigestAuthTestFromHTTPWatch(T& cli) {
template <typename T> void DigestAuthTestFromHTTPWatch(T &cli) {
cli.set_proxy("localhost", 3129);
cli.set_proxy_digest_auth("hello", "world");
@ -181,7 +179,8 @@ void DigestAuthTestFromHTTPWatch(T& cli) {
for (auto path : paths) {
auto res = cli.Get(path.c_str());
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(StatusCode::OK_200, res->status);
}
@ -216,8 +215,7 @@ TEST(DigestAuthTest, NoSSL) {
// ----------------------------------------------------------------------------
template <typename T>
void KeepAliveTest(T& cli, bool basic) {
template <typename T> void KeepAliveTest(T &cli, bool basic) {
cli.set_proxy("localhost", basic ? 3128 : 3129);
if (basic) {
cli.set_proxy_basic_auth("hello", "world");
@ -249,9 +247,10 @@ void KeepAliveTest(T& cli, bool basic) {
"/httpbin/digest-auth/auth-int/hello/world/MD5",
};
for (auto path: paths) {
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("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n",
res->body);
EXPECT_EQ(StatusCode::OK_200, res->status);
}
}

7
test/www/meson.build Normal file
View File

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: 2024 Andrea Pappacoda
#
# SPDX-License-Identifier: MIT
configure_file(input: 'empty_file', output: 'empty_file', copy: true)
configure_file(input: 'file', output: 'file', copy: true)
subdir('dir')

View File

@ -0,0 +1 @@
日本語コンテンツ