Compare commits
2 Commits
master
...
cleaner-ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01d9579dbf | ||
|
|
335246bc7d |
4
.github/workflows/abidiff.yaml
vendored
4
.github/workflows/abidiff.yaml
vendored
@ -5,10 +5,6 @@ name: abidiff
|
|||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: sh
|
shell: sh
|
||||||
|
|||||||
6
.github/workflows/cifuzz.yaml
vendored
6
.github/workflows/cifuzz.yaml
vendored
@ -1,11 +1,5 @@
|
|||||||
name: CIFuzz
|
name: CIFuzz
|
||||||
|
|
||||||
on: [pull_request]
|
on: [pull_request]
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Fuzzing:
|
Fuzzing:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
61
.github/workflows/test.yaml
vendored
61
.github/workflows/test.yaml
vendored
@ -20,10 +20,6 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: true
|
default: true
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GTEST_FILTER: ${{ github.event.inputs.gtest_filter || '*' }}
|
GTEST_FILTER: ${{ github.event.inputs.gtest_filter || '*' }}
|
||||||
|
|
||||||
@ -47,14 +43,21 @@ jobs:
|
|||||||
(github.event_name == 'pull_request' &&
|
(github.event_name == 'pull_request' &&
|
||||||
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
|
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')
|
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
select_impl: ['select', 'poll']
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: install libraries
|
- name: install libraries
|
||||||
run: sudo apt-get update && sudo apt-get install -y libbrotli-dev libcurl4-openssl-dev
|
run: sudo apt-get update && sudo apt-get install -y libbrotli-dev libcurl4-openssl-dev
|
||||||
- name: build and run tests
|
- name: build and run tests
|
||||||
|
env:
|
||||||
|
SELECT_IMPL: ${{ matrix.select_impl }}
|
||||||
run: cd test && make
|
run: cd test && make
|
||||||
- name: run fuzz test target
|
- name: run fuzz test target
|
||||||
|
env:
|
||||||
|
SELECT_IMPL: ${{ matrix.select_impl }}
|
||||||
run: cd test && make fuzz_test
|
run: cd test && make fuzz_test
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
@ -64,12 +67,19 @@ jobs:
|
|||||||
(github.event_name == 'pull_request' &&
|
(github.event_name == 'pull_request' &&
|
||||||
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
|
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')
|
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_macos == 'true')
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
select_impl: ['select', 'poll']
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: build and run tests
|
- name: build and run tests
|
||||||
|
env:
|
||||||
|
SELECT_IMPL: ${{ matrix.select_impl }}
|
||||||
run: cd test && make
|
run: cd test && make
|
||||||
- name: run fuzz test target
|
- name: run fuzz test target
|
||||||
|
env:
|
||||||
|
SELECT_IMPL: ${{ matrix.select_impl }}
|
||||||
run: cd test && make fuzz_test
|
run: cd test && make fuzz_test
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
@ -81,12 +91,7 @@ jobs:
|
|||||||
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_windows == 'true')
|
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_windows == 'true')
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
config:
|
select_impl: ['select', 'poll']
|
||||||
- with_ssl: false
|
|
||||||
name: without SSL
|
|
||||||
- with_ssl: true
|
|
||||||
name: with SSL
|
|
||||||
name: windows ${{ matrix.config.name }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare Git for Checkout on Windows
|
- name: Prepare Git for Checkout on Windows
|
||||||
run: |
|
run: |
|
||||||
@ -102,25 +107,41 @@ jobs:
|
|||||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||||
- name: Setup msbuild on windows
|
- name: Setup msbuild on windows
|
||||||
uses: microsoft/setup-msbuild@v2
|
uses: microsoft/setup-msbuild@v2
|
||||||
- name: Install vcpkg dependencies
|
- name: Install libraries
|
||||||
run: vcpkg install gtest curl zlib brotli
|
run: |
|
||||||
- name: Install OpenSSL
|
vcpkg install gtest curl zlib brotli
|
||||||
if: ${{ matrix.config.with_ssl }}
|
choco install openssl
|
||||||
run: choco install openssl
|
|
||||||
- name: Configure CMake ${{ matrix.config.name }}
|
- name: Configure CMake with SSL
|
||||||
run: >
|
run: >
|
||||||
cmake -B build -S .
|
cmake -B build -S .
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
|
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
|
||||||
-DHTTPLIB_TEST=ON
|
-DHTTPLIB_TEST=ON
|
||||||
|
-DHTTPLIB_REQUIRE_OPENSSL=ON
|
||||||
-DHTTPLIB_REQUIRE_ZLIB=ON
|
-DHTTPLIB_REQUIRE_ZLIB=ON
|
||||||
-DHTTPLIB_REQUIRE_BROTLI=ON
|
-DHTTPLIB_REQUIRE_BROTLI=ON
|
||||||
-DHTTPLIB_REQUIRE_OPENSSL=${{ matrix.config.with_ssl && 'ON' || 'OFF' }}
|
-DHTTPLIB_USE_SELECT=${{ matrix.select_impl == 'select' && 'ON' || 'OFF' }}
|
||||||
- name: Build ${{ matrix.config.name }}
|
- name: Build with with SSL
|
||||||
run: cmake --build build --config Release -- /v:m /clp:ShowCommandLine
|
run: cmake --build build --config Release -- /v:m /clp:ShowCommandLine /nologo
|
||||||
- name: Run tests ${{ matrix.config.name }}
|
- name: Run tests with SSL
|
||||||
run: ctest --output-on-failure --test-dir build -C Release
|
run: ctest --output-on-failure --test-dir build -C Release
|
||||||
|
|
||||||
|
- name: Configure CMake without SSL
|
||||||
|
run: >
|
||||||
|
cmake -B build-no-ssl -S .
|
||||||
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||||
|
-DHTTPLIB_TEST=ON
|
||||||
|
-DHTTPLIB_REQUIRE_OPENSSL=OFF
|
||||||
|
-DHTTPLIB_REQUIRE_ZLIB=ON
|
||||||
|
-DHTTPLIB_REQUIRE_BROTLI=ON
|
||||||
|
-DHTTPLIB_USE_SELECT=${{ matrix.select_impl == 'select' && 'ON' || 'OFF' }}
|
||||||
|
- name: Build without SSL
|
||||||
|
run: cmake --build build-no-ssl --config Release -- /v:m /clp:ShowCommandLine /nologo
|
||||||
|
- name: Run tests without SSL
|
||||||
|
run: ctest --output-on-failure --test-dir build-no-ssl -C Release
|
||||||
env:
|
env:
|
||||||
VCPKG_ROOT: "C:/vcpkg"
|
VCPKG_ROOT: "C:/vcpkg"
|
||||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
* HTTPLIB_REQUIRE_ZLIB (default off)
|
* HTTPLIB_REQUIRE_ZLIB (default off)
|
||||||
* HTTPLIB_REQUIRE_BROTLI (default off)
|
* HTTPLIB_REQUIRE_BROTLI (default off)
|
||||||
* HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on)
|
* HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on)
|
||||||
|
* HTTPLIB_USE_SELECT (default off) choose between select() and poll()
|
||||||
* HTTPLIB_COMPILE (default off)
|
* HTTPLIB_COMPILE (default off)
|
||||||
* HTTPLIB_INSTALL (default on)
|
* HTTPLIB_INSTALL (default on)
|
||||||
* HTTPLIB_TEST (default off)
|
* HTTPLIB_TEST (default off)
|
||||||
@ -46,6 +47,7 @@
|
|||||||
* HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled.
|
* HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled.
|
||||||
* HTTPLIB_IS_USING_BROTLI - a bool for if Brotli support is enabled.
|
* HTTPLIB_IS_USING_BROTLI - a bool for if Brotli support is enabled.
|
||||||
* HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN - a bool for if support of loading system certs from the Apple Keychain is enabled.
|
* HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN - a bool for if support of loading system certs from the Apple Keychain is enabled.
|
||||||
|
* HTTPLIB_IS_USING_SELECT - a bool for if select() is used instead of poll().
|
||||||
* HTTPLIB_IS_COMPILED - a bool for if the library is compiled, or otherwise header-only.
|
* HTTPLIB_IS_COMPILED - a bool for if the library is compiled, or otherwise header-only.
|
||||||
* HTTPLIB_INCLUDE_DIR - the root path to httplib's header (e.g. /usr/include).
|
* HTTPLIB_INCLUDE_DIR - the root path to httplib's header (e.g. /usr/include).
|
||||||
* HTTPLIB_LIBRARY - the full path to the library if compiled (e.g. /usr/lib/libhttplib.so).
|
* HTTPLIB_LIBRARY - the full path to the library if compiled (e.g. /usr/lib/libhttplib.so).
|
||||||
@ -101,6 +103,7 @@ option(HTTPLIB_TEST "Enables testing and builds tests" OFF)
|
|||||||
option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF)
|
option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF)
|
||||||
option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON)
|
option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON)
|
||||||
option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system certs from the Apple Keychain." ON)
|
option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system certs from the Apple Keychain." ON)
|
||||||
|
option(HTTPLIB_USE_SELECT "Uses select() instead of poll()." OFF)
|
||||||
# Defaults to static library
|
# Defaults to static library
|
||||||
option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF)
|
option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF)
|
||||||
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
|
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
|
||||||
@ -112,6 +115,7 @@ endif()
|
|||||||
# Set some variables that are used in-tree and while building based on our options
|
# Set some variables that are used in-tree and while building based on our options
|
||||||
set(HTTPLIB_IS_COMPILED ${HTTPLIB_COMPILE})
|
set(HTTPLIB_IS_COMPILED ${HTTPLIB_COMPILE})
|
||||||
set(HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN ${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN})
|
set(HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN ${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN})
|
||||||
|
set(HTTPLIB_IS_USING_SELECT ${HTTPLIB_USE_SELECT})
|
||||||
|
|
||||||
# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
|
# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||||
@ -238,6 +242,7 @@ target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
|||||||
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
|
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
|
||||||
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_SUPPORT>
|
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_SUPPORT>
|
||||||
$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN}>>:CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN>
|
$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN}>>:CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN>
|
||||||
|
$<$<BOOL:${HTTPLIB_IS_USING_SELECT}>:CPPHTTPLIB_USE_SELECT>
|
||||||
)
|
)
|
||||||
|
|
||||||
# CMake configuration files installation directory
|
# CMake configuration files installation directory
|
||||||
|
|||||||
17
README.md
17
README.md
@ -462,7 +462,7 @@ Please see [Server example](https://github.com/yhirose/cpp-httplib/blob/master/e
|
|||||||
|
|
||||||
### Default thread pool support
|
### Default thread pool support
|
||||||
|
|
||||||
`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`.
|
`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`.
|
||||||
|
|
||||||
If you want to set the thread count at runtime, there is no convenient way... But here is how.
|
If you want to set the thread count at runtime, there is no convenient way... But here is how.
|
||||||
|
|
||||||
@ -578,7 +578,7 @@ auto res = cli.Get("/hi", headers);
|
|||||||
```
|
```
|
||||||
or
|
or
|
||||||
```c++
|
```c++
|
||||||
auto res = cli.Get("/hi", {{"Hello", "World!"}});
|
auto res = cli.Get("/hi", httplib::Headers{{"Hello", "World!"}});
|
||||||
```
|
```
|
||||||
or
|
or
|
||||||
```c++
|
```c++
|
||||||
@ -675,7 +675,7 @@ auto res = cli.Get("/large-data",
|
|||||||
std::string body;
|
std::string body;
|
||||||
|
|
||||||
auto res = cli.Get(
|
auto res = cli.Get(
|
||||||
"/stream", Headers(),
|
"/stream",
|
||||||
[&](const Response &response) {
|
[&](const Response &response) {
|
||||||
EXPECT_EQ(StatusCode::OK_200, response.status);
|
EXPECT_EQ(StatusCode::OK_200, response.status);
|
||||||
return true; // return 'false' if you want to cancel the request.
|
return true; // return 'false' if you want to cancel the request.
|
||||||
@ -847,13 +847,13 @@ The default `Accept-Encoding` value contains all possible compression types. So,
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
res = cli.Get("/resource/foo");
|
res = cli.Get("/resource/foo");
|
||||||
res = cli.Get("/resource/foo", {{"Accept-Encoding", "gzip, deflate, br"}});
|
res = cli.Get("/resource/foo", httplib::Headers{{"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.
|
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++
|
```c++
|
||||||
res = cli.Get("/resource/foo", {{"Accept-Encoding", ""}});
|
res = cli.Get("/resource/foo", httplib::Headers{{"Accept-Encoding", ""}});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compress request body on client
|
### Compress request body on client
|
||||||
@ -872,6 +872,11 @@ res->body; // Compressed data
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use `select()` instead of `poll()`
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
cpp-httplib defaults to the widely supported `poll()` system call. If your OS lacks support for `poll()`, define `CPPHTTPLIB_USE_SELECT` to use `select()` instead.
|
||||||
|
|
||||||
Unix Domain Socket Support
|
Unix Domain Socket Support
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
@ -879,7 +884,7 @@ Unix Domain Socket support is available on Linux and macOS.
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
// Server
|
// Server
|
||||||
httplib::Server svr;
|
httplib::Server svr("./my-socket.sock");
|
||||||
svr.set_address_family(AF_UNIX).listen("./my-socket.sock", 80);
|
svr.set_address_family(AF_UNIX).listen("./my-socket.sock", 80);
|
||||||
|
|
||||||
// Client
|
// Client
|
||||||
|
|||||||
@ -41,7 +41,7 @@ std::string log(auto &req, auto &res) {
|
|||||||
auto http_referer = "-"; // TODO:
|
auto http_referer = "-"; // TODO:
|
||||||
auto http_user_agent = req.get_header_value("User-Agent", "-");
|
auto http_user_agent = req.get_header_value("User-Agent", "-");
|
||||||
|
|
||||||
// NOTE: From NGINX default access log format
|
// NOTE: From NGINX defualt access log format
|
||||||
// log_format combined '$remote_addr - $remote_user [$time_local] '
|
// log_format combined '$remote_addr - $remote_user [$time_local] '
|
||||||
// '"$request" $status $body_bytes_sent '
|
// '"$request" $status $body_bytes_sent '
|
||||||
// '"$http_referer" "$http_user_agent"';
|
// '"$http_referer" "$http_user_agent"';
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
CXX = clang++
|
CXX = clang++
|
||||||
CXXFLAGS = -g -std=c++11 -I. -Wall -Wextra -Wtype-limits -Wconversion -Wshadow # -fno-exceptions -DCPPHTTPLIB_NO_EXCEPTIONS -fsanitize=address
|
CXXFLAGS = -g -std=c++11 -I. -Wall -Wextra -Wtype-limits -Wconversion -Wshadow # -fno-exceptions -DCPPHTTPLIB_NO_EXCEPTIONS -fsanitize=address
|
||||||
|
|
||||||
|
ifeq ($(SELECT_IMPL),select)
|
||||||
|
CXXFLAGS += -DCPPHTTPLIB_USE_SELECT
|
||||||
|
endif
|
||||||
|
|
||||||
PREFIX ?= $(shell brew --prefix)
|
PREFIX ?= $(shell brew --prefix)
|
||||||
|
|
||||||
OPENSSL_DIR = $(PREFIX)/opt/openssl@3
|
OPENSSL_DIR = $(PREFIX)/opt/openssl@3
|
||||||
|
|||||||
@ -25,9 +25,7 @@ public:
|
|||||||
|
|
||||||
bool is_readable() const override { return true; }
|
bool is_readable() const override { return true; }
|
||||||
|
|
||||||
bool wait_readable() const override { return true; }
|
bool is_writable() const override { return true; }
|
||||||
|
|
||||||
bool wait_writable() const override { return true; }
|
|
||||||
|
|
||||||
void get_remote_ip_and_port(std::string &ip, int &port) const override {
|
void get_remote_ip_and_port(std::string &ip, int &port) const override {
|
||||||
ip = "127.0.0.1";
|
ip = "127.0.0.1";
|
||||||
|
|||||||
459
test/test.cc
459
test/test.cc
@ -156,7 +156,7 @@ TEST_F(UnixSocketTest, abstract) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(SocketStream, wait_writable_UNIX) {
|
TEST(SocketStream, is_writable_UNIX) {
|
||||||
int fds[2];
|
int fds[2];
|
||||||
ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, fds));
|
ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, fds));
|
||||||
|
|
||||||
@ -167,17 +167,17 @@ TEST(SocketStream, wait_writable_UNIX) {
|
|||||||
};
|
};
|
||||||
asSocketStream(fds[0], [&](Stream &s0) {
|
asSocketStream(fds[0], [&](Stream &s0) {
|
||||||
EXPECT_EQ(s0.socket(), fds[0]);
|
EXPECT_EQ(s0.socket(), fds[0]);
|
||||||
EXPECT_TRUE(s0.wait_writable());
|
EXPECT_TRUE(s0.is_writable());
|
||||||
|
|
||||||
EXPECT_EQ(0, close(fds[1]));
|
EXPECT_EQ(0, close(fds[1]));
|
||||||
EXPECT_FALSE(s0.wait_writable());
|
EXPECT_FALSE(s0.is_writable());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
EXPECT_EQ(0, close(fds[0]));
|
EXPECT_EQ(0, close(fds[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SocketStream, wait_writable_INET) {
|
TEST(SocketStream, is_writable_INET) {
|
||||||
sockaddr_in addr;
|
sockaddr_in addr;
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
@ -212,7 +212,7 @@ TEST(SocketStream, wait_writable_INET) {
|
|||||||
};
|
};
|
||||||
asSocketStream(disconnected_svr_sock, [&](Stream &ss) {
|
asSocketStream(disconnected_svr_sock, [&](Stream &ss) {
|
||||||
EXPECT_EQ(ss.socket(), disconnected_svr_sock);
|
EXPECT_EQ(ss.socket(), disconnected_svr_sock);
|
||||||
EXPECT_FALSE(ss.wait_writable());
|
EXPECT_FALSE(ss.is_writable());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -524,37 +524,37 @@ TEST(GetHeaderValueTest, RegularInvalidValueInt) {
|
|||||||
|
|
||||||
TEST(GetHeaderValueTest, Range) {
|
TEST(GetHeaderValueTest, Range) {
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{1, -1}})};
|
auto headers = Headers{make_range_header({{1, -1}})};
|
||||||
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=1-", val);
|
EXPECT_STREQ("bytes=1-", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{-1, 1}})};
|
auto headers = Headers{make_range_header({{-1, 1}})};
|
||||||
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=-1", val);
|
EXPECT_STREQ("bytes=-1", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{1, 10}})};
|
auto headers = Headers{make_range_header({{1, 10}})};
|
||||||
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=1-10", val);
|
EXPECT_STREQ("bytes=1-10", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{1, 10}, {100, -1}})};
|
auto headers = Headers{make_range_header({{1, 10}, {100, -1}})};
|
||||||
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=1-10, 100-", val);
|
EXPECT_STREQ("bytes=1-10, 100-", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{1, 10}, {100, 200}})};
|
auto headers = Headers{make_range_header({{1, 10}, {100, 200}})};
|
||||||
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=1-10, 100-200", val);
|
EXPECT_STREQ("bytes=1-10, 100-200", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{0, 0}, {-1, 1}})};
|
auto headers = Headers{make_range_header({{0, 0}, {-1, 1}})};
|
||||||
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=0-0, -1", val);
|
EXPECT_STREQ("bytes=0-0, -1", val);
|
||||||
}
|
}
|
||||||
@ -800,24 +800,47 @@ TEST(ChunkedEncodingTest, WithResponseHandlerAndContentReceiver_Online) {
|
|||||||
#endif
|
#endif
|
||||||
cli.set_connection_timeout(2);
|
cli.set_connection_timeout(2);
|
||||||
|
|
||||||
std::string body;
|
{
|
||||||
auto res = cli.Get(
|
std::string body;
|
||||||
"/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137",
|
auto res = cli.Get(
|
||||||
[&](const Response &response) {
|
"/httpgallery/chunked/chunkedimage.aspx",
|
||||||
EXPECT_EQ(StatusCode::OK_200, response.status);
|
[&](const Response &response) {
|
||||||
return true;
|
EXPECT_EQ(StatusCode::OK_200, response.status);
|
||||||
},
|
return true;
|
||||||
[&](const char *data, size_t data_length) {
|
},
|
||||||
body.append(data, data_length);
|
[&](const char *data, size_t data_length) {
|
||||||
return true;
|
body.append(data, data_length);
|
||||||
});
|
return true;
|
||||||
ASSERT_TRUE(res);
|
});
|
||||||
|
ASSERT_TRUE(res);
|
||||||
|
|
||||||
std::string out;
|
std::string out;
|
||||||
detail::read_file("./image.jpg", out);
|
detail::read_file("./image.jpg", out);
|
||||||
|
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
EXPECT_EQ(out, body);
|
EXPECT_EQ(out, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string body;
|
||||||
|
auto res = cli.Get(
|
||||||
|
"/httpgallery/chunked/chunkedimage.aspx", Params{},
|
||||||
|
[&](const Response &response) {
|
||||||
|
EXPECT_EQ(StatusCode::OK_200, response.status);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[&](const char *data, size_t data_length) {
|
||||||
|
body.append(data, data_length);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
ASSERT_TRUE(res);
|
||||||
|
|
||||||
|
std::string out;
|
||||||
|
detail::read_file("./image.jpg", out);
|
||||||
|
|
||||||
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
|
EXPECT_EQ(out, body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RangeTest, FromHTTPBin_Online) {
|
TEST(RangeTest, FromHTTPBin_Online) {
|
||||||
@ -846,7 +869,7 @@ TEST(RangeTest, FromHTTPBin_Online) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{1, -1}})};
|
auto headers = Headers{make_range_header({{1, -1}})};
|
||||||
auto res = cli.Get(path, headers);
|
auto res = cli.Get(path, headers);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("bcdefghijklmnopqrstuvwxyzabcdef", res->body);
|
EXPECT_EQ("bcdefghijklmnopqrstuvwxyzabcdef", res->body);
|
||||||
@ -854,7 +877,7 @@ TEST(RangeTest, FromHTTPBin_Online) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{1, 10}})};
|
auto headers = Headers{make_range_header({{1, 10}})};
|
||||||
auto res = cli.Get(path, headers);
|
auto res = cli.Get(path, headers);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("bcdefghijk", res->body);
|
EXPECT_EQ("bcdefghijk", res->body);
|
||||||
@ -862,7 +885,7 @@ TEST(RangeTest, FromHTTPBin_Online) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{0, 31}})};
|
auto headers = Headers{make_range_header({{0, 31}})};
|
||||||
auto res = cli.Get(path, headers);
|
auto res = cli.Get(path, headers);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("abcdefghijklmnopqrstuvwxyzabcdef", res->body);
|
EXPECT_EQ("abcdefghijklmnopqrstuvwxyzabcdef", res->body);
|
||||||
@ -870,7 +893,7 @@ TEST(RangeTest, FromHTTPBin_Online) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{0, -1}})};
|
auto headers = Headers{make_range_header({{0, -1}})};
|
||||||
auto res = cli.Get(path, headers);
|
auto res = cli.Get(path, headers);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("abcdefghijklmnopqrstuvwxyzabcdef", res->body);
|
EXPECT_EQ("abcdefghijklmnopqrstuvwxyzabcdef", res->body);
|
||||||
@ -878,7 +901,7 @@ TEST(RangeTest, FromHTTPBin_Online) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = {make_range_header({{0, 32}})};
|
auto headers = Headers{make_range_header({{0, 32}})};
|
||||||
auto res = cli.Get(path, headers);
|
auto res = cli.Get(path, headers);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
@ -1064,9 +1087,8 @@ TEST(CancelTest, NoCancelPost) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Post("/", JSON_DATA, "application/json",
|
||||||
cli.Post("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return true; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return true; });
|
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("Hello World!", res->body);
|
EXPECT_EQ("Hello World!", res->body);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
@ -1091,9 +1113,8 @@ TEST(CancelTest, WithCancelSmallPayloadPost) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Post("/", JSON_DATA, "application/json",
|
||||||
cli.Post("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return false; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return false; });
|
|
||||||
ASSERT_TRUE(!res);
|
ASSERT_TRUE(!res);
|
||||||
EXPECT_EQ(Error::Canceled, res.error());
|
EXPECT_EQ(Error::Canceled, res.error());
|
||||||
}
|
}
|
||||||
@ -1117,9 +1138,8 @@ TEST(CancelTest, WithCancelLargePayloadPost) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Post("/", JSON_DATA, "application/json",
|
||||||
cli.Post("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return false; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return false; });
|
|
||||||
ASSERT_TRUE(!res);
|
ASSERT_TRUE(!res);
|
||||||
EXPECT_EQ(Error::Canceled, res.error());
|
EXPECT_EQ(Error::Canceled, res.error());
|
||||||
}
|
}
|
||||||
@ -1143,9 +1163,8 @@ TEST(CancelTest, NoCancelPut) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Put("/", JSON_DATA, "application/json",
|
||||||
cli.Put("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return true; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return true; });
|
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("Hello World!", res->body);
|
EXPECT_EQ("Hello World!", res->body);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
@ -1170,9 +1189,8 @@ TEST(CancelTest, WithCancelSmallPayloadPut) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Put("/", JSON_DATA, "application/json",
|
||||||
cli.Put("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return false; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return false; });
|
|
||||||
ASSERT_TRUE(!res);
|
ASSERT_TRUE(!res);
|
||||||
EXPECT_EQ(Error::Canceled, res.error());
|
EXPECT_EQ(Error::Canceled, res.error());
|
||||||
}
|
}
|
||||||
@ -1196,9 +1214,8 @@ TEST(CancelTest, WithCancelLargePayloadPut) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Put("/", JSON_DATA, "application/json",
|
||||||
cli.Put("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return false; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return false; });
|
|
||||||
ASSERT_TRUE(!res);
|
ASSERT_TRUE(!res);
|
||||||
EXPECT_EQ(Error::Canceled, res.error());
|
EXPECT_EQ(Error::Canceled, res.error());
|
||||||
}
|
}
|
||||||
@ -1222,9 +1239,8 @@ TEST(CancelTest, NoCancelPatch) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Patch("/", JSON_DATA, "application/json",
|
||||||
cli.Patch("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return true; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return true; });
|
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("Hello World!", res->body);
|
EXPECT_EQ("Hello World!", res->body);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
@ -1249,9 +1265,8 @@ TEST(CancelTest, WithCancelSmallPayloadPatch) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Patch("/", JSON_DATA, "application/json",
|
||||||
cli.Patch("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return false; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return false; });
|
|
||||||
ASSERT_TRUE(!res);
|
ASSERT_TRUE(!res);
|
||||||
EXPECT_EQ(Error::Canceled, res.error());
|
EXPECT_EQ(Error::Canceled, res.error());
|
||||||
}
|
}
|
||||||
@ -1275,9 +1290,8 @@ TEST(CancelTest, WithCancelLargePayloadPatch) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Patch("/", JSON_DATA, "application/json",
|
||||||
cli.Patch("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return false; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return false; });
|
|
||||||
ASSERT_TRUE(!res);
|
ASSERT_TRUE(!res);
|
||||||
EXPECT_EQ(Error::Canceled, res.error());
|
EXPECT_EQ(Error::Canceled, res.error());
|
||||||
}
|
}
|
||||||
@ -1301,9 +1315,8 @@ TEST(CancelTest, NoCancelDelete) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Delete("/", JSON_DATA, "application/json",
|
||||||
cli.Delete("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return true; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return true; });
|
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("Hello World!", res->body);
|
EXPECT_EQ("Hello World!", res->body);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
@ -1328,9 +1341,8 @@ TEST(CancelTest, WithCancelSmallPayloadDelete) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Delete("/", JSON_DATA, "application/json",
|
||||||
cli.Delete("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return false; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return false; });
|
|
||||||
ASSERT_TRUE(!res);
|
ASSERT_TRUE(!res);
|
||||||
EXPECT_EQ(Error::Canceled, res.error());
|
EXPECT_EQ(Error::Canceled, res.error());
|
||||||
}
|
}
|
||||||
@ -1354,9 +1366,8 @@ TEST(CancelTest, WithCancelLargePayloadDelete) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
|
|
||||||
auto res =
|
auto res = cli.Delete("/", JSON_DATA, "application/json",
|
||||||
cli.Delete("/", Headers(), JSON_DATA.data(), JSON_DATA.size(),
|
[](uint64_t, uint64_t) { return false; });
|
||||||
"application/json", [](uint64_t, uint64_t) { return false; });
|
|
||||||
ASSERT_TRUE(!res);
|
ASSERT_TRUE(!res);
|
||||||
EXPECT_EQ(Error::Canceled, res.error());
|
EXPECT_EQ(Error::Canceled, res.error());
|
||||||
}
|
}
|
||||||
@ -1385,8 +1396,8 @@ TEST(BaseAuthTest, FromHTTPWatch_Online) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto res =
|
auto res = cli.Get(
|
||||||
cli.Get(path, {make_basic_authentication_header("hello", "world")});
|
path, Headers{make_basic_authentication_header("hello", "world")});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n",
|
EXPECT_EQ("{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n",
|
||||||
res->body);
|
res->body);
|
||||||
@ -1603,7 +1614,7 @@ TEST(HttpsToHttpRedirectTest2, Redirect_Online) {
|
|||||||
params.emplace("url", "http://www.google.com");
|
params.emplace("url", "http://www.google.com");
|
||||||
params.emplace("status_code", "302");
|
params.emplace("status_code", "302");
|
||||||
|
|
||||||
auto res = cli.Get("/httpbin/redirect-to", params, Headers{});
|
auto res = cli.Get("/httpbin/redirect-to", params);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
@ -1615,7 +1626,7 @@ TEST(HttpsToHttpRedirectTest3, Redirect_Online) {
|
|||||||
Params params;
|
Params params;
|
||||||
params.emplace("url", "http://www.google.com");
|
params.emplace("url", "http://www.google.com");
|
||||||
|
|
||||||
auto res = cli.Get("/httpbin/redirect-to?status_code=302", params, Headers{});
|
auto res = cli.Get("/httpbin/redirect-to?status_code=302", params);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
@ -2041,7 +2052,7 @@ TEST(ErrorHandlerTest, ContentLength) {
|
|||||||
{
|
{
|
||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
|
|
||||||
auto res = cli.Get("/hi", {{"Accept-Encoding", ""}});
|
auto res = cli.Get("/hi", Headers{{"Accept-Encoding", ""}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
||||||
@ -2124,7 +2135,7 @@ TEST(ExceptionTest, WithExceptionHandler) {
|
|||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
|
|
||||||
for (size_t j = 0; j < 100; j++) {
|
for (size_t j = 0; j < 100; j++) {
|
||||||
auto res = cli.Get("/hi", {{"Accept-Encoding", ""}});
|
auto res = cli.Get("/hi", Headers{{"Accept-Encoding", ""}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::InternalServerError_500, res->status);
|
EXPECT_EQ(StatusCode::InternalServerError_500, res->status);
|
||||||
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
||||||
@ -2135,7 +2146,7 @@ TEST(ExceptionTest, WithExceptionHandler) {
|
|||||||
cli.set_keep_alive(true);
|
cli.set_keep_alive(true);
|
||||||
|
|
||||||
for (size_t j = 0; j < 100; j++) {
|
for (size_t j = 0; j < 100; j++) {
|
||||||
auto res = cli.Get("/hi", {{"Accept-Encoding", ""}});
|
auto res = cli.Get("/hi", Headers{{"Accept-Encoding", ""}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::InternalServerError_500, res->status);
|
EXPECT_EQ(StatusCode::InternalServerError_500, res->status);
|
||||||
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
||||||
@ -3079,7 +3090,7 @@ TEST_F(ServerTest, GetFileContent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetFileContentWithRange) {
|
TEST_F(ServerTest, GetFileContentWithRange) {
|
||||||
auto res = cli_.Get("/file_content", {{make_range_header({{1, 3}})}});
|
auto res = cli_.Get("/file_content", Headers{{make_range_header({{1, 3}})}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
||||||
@ -3401,7 +3412,7 @@ TEST_F(ServerTest, UserDefinedMIMETypeMapping) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, StaticFileRange) {
|
TEST_F(ServerTest, StaticFileRange) {
|
||||||
auto res = cli_.Get("/dir/test.abcde", {{make_range_header({{2, 3}})}});
|
auto res = cli_.Get("/dir/test.abcde", Headers{make_range_header({{2, 3}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("text/abcde", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/abcde", res->get_header_value("Content-Type"));
|
||||||
@ -3412,8 +3423,8 @@ TEST_F(ServerTest, StaticFileRange) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, StaticFileRanges) {
|
TEST_F(ServerTest, StaticFileRanges) {
|
||||||
auto res =
|
auto res = cli_.Get("/dir/test.abcde",
|
||||||
cli_.Get("/dir/test.abcde", {{make_range_header({{1, 2}, {4, -1}})}});
|
Headers{make_range_header({{1, 2}, {4, -1}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
@ -3425,7 +3436,7 @@ TEST_F(ServerTest, StaticFileRanges) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, StaticFileRangeHead) {
|
TEST_F(ServerTest, StaticFileRangeHead) {
|
||||||
auto res = cli_.Head("/dir/test.abcde", {{make_range_header({{2, 3}})}});
|
auto res = cli_.Head("/dir/test.abcde", Headers{make_range_header({{2, 3}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("text/abcde", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/abcde", res->get_header_value("Content-Type"));
|
||||||
@ -3435,7 +3446,7 @@ TEST_F(ServerTest, StaticFileRangeHead) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, StaticFileRangeBigFile) {
|
TEST_F(ServerTest, StaticFileRangeBigFile) {
|
||||||
auto res = cli_.Get("/dir/1MB.txt", {{make_range_header({{-1, 5}})}});
|
auto res = cli_.Get("/dir/1MB.txt", Headers{make_range_header({{-1, 5}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
||||||
@ -3447,7 +3458,7 @@ TEST_F(ServerTest, StaticFileRangeBigFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, StaticFileRangeBigFile2) {
|
TEST_F(ServerTest, StaticFileRangeBigFile2) {
|
||||||
auto res = cli_.Get("/dir/1MB.txt", {{make_range_header({{1, 4097}})}});
|
auto res = cli_.Get("/dir/1MB.txt", Headers{make_range_header({{1, 4097}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
||||||
@ -3789,7 +3800,7 @@ TEST_F(ServerTest, CaseInsensitiveTransferEncoding) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamed2) {
|
TEST_F(ServerTest, GetStreamed2) {
|
||||||
auto res = cli_.Get("/streamed", {{make_range_header({{2, 3}})}});
|
auto res = cli_.Get("/streamed", Headers{make_range_header({{2, 3}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("2", res->get_header_value("Content-Length"));
|
EXPECT_EQ("2", res->get_header_value("Content-Length"));
|
||||||
@ -3807,7 +3818,8 @@ TEST_F(ServerTest, GetStreamed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithRange1) {
|
TEST_F(ServerTest, GetStreamedWithRange1) {
|
||||||
auto res = cli_.Get("/streamed-with-range", {{make_range_header({{3, 5}})}});
|
auto res =
|
||||||
|
cli_.Get("/streamed-with-range", Headers{make_range_header({{3, 5}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("3", res->get_header_value("Content-Length"));
|
EXPECT_EQ("3", res->get_header_value("Content-Length"));
|
||||||
@ -3817,7 +3829,8 @@ TEST_F(ServerTest, GetStreamedWithRange1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithRange2) {
|
TEST_F(ServerTest, GetStreamedWithRange2) {
|
||||||
auto res = cli_.Get("/streamed-with-range", {{make_range_header({{1, -1}})}});
|
auto res =
|
||||||
|
cli_.Get("/streamed-with-range", Headers{make_range_header({{1, -1}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("6", res->get_header_value("Content-Length"));
|
EXPECT_EQ("6", res->get_header_value("Content-Length"));
|
||||||
@ -3827,7 +3840,7 @@ TEST_F(ServerTest, GetStreamedWithRange2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithRangeSuffix1) {
|
TEST_F(ServerTest, GetStreamedWithRangeSuffix1) {
|
||||||
auto res = cli_.Get("/streamed-with-range", {{"Range", "bytes=-3"}});
|
auto res = cli_.Get("/streamed-with-range", Headers{{"Range", "bytes=-3"}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("3", res->get_header_value("Content-Length"));
|
EXPECT_EQ("3", res->get_header_value("Content-Length"));
|
||||||
@ -3837,7 +3850,8 @@ TEST_F(ServerTest, GetStreamedWithRangeSuffix1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithRangeSuffix2) {
|
TEST_F(ServerTest, GetStreamedWithRangeSuffix2) {
|
||||||
auto res = cli_.Get("/streamed-with-range?error", {{"Range", "bytes=-9999"}});
|
auto res =
|
||||||
|
cli_.Get("/streamed-with-range?error", Headers{{"Range", "bytes=-9999"}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
||||||
@ -3846,8 +3860,9 @@ TEST_F(ServerTest, GetStreamedWithRangeSuffix2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithRangeError) {
|
TEST_F(ServerTest, GetStreamedWithRangeError) {
|
||||||
auto res = cli_.Get("/streamed-with-range",
|
auto res =
|
||||||
{{"Range", "bytes=92233720368547758079223372036854775806-"
|
cli_.Get("/streamed-with-range",
|
||||||
|
Headers{{"Range", "bytes=92233720368547758079223372036854775806-"
|
||||||
"92233720368547758079223372036854775807"}});
|
"92233720368547758079223372036854775807"}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
@ -3859,8 +3874,9 @@ TEST_F(ServerTest, GetStreamedWithRangeError) {
|
|||||||
TEST_F(ServerTest, GetRangeWithMaxLongLength) {
|
TEST_F(ServerTest, GetRangeWithMaxLongLength) {
|
||||||
auto res = cli_.Get(
|
auto res = cli_.Get(
|
||||||
"/with-range",
|
"/with-range",
|
||||||
{{"Range", "bytes=0-" + std::to_string(std::numeric_limits<long>::max())},
|
Headers{{"Range",
|
||||||
{"Accept-Encoding", ""}});
|
"bytes=0-" + std::to_string(std::numeric_limits<long>::max())},
|
||||||
|
{"Accept-Encoding", ""}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("7", res->get_header_value("Content-Length"));
|
EXPECT_EQ("7", res->get_header_value("Content-Length"));
|
||||||
@ -3870,7 +3886,7 @@ TEST_F(ServerTest, GetRangeWithMaxLongLength) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetRangeWithZeroToInfinite) {
|
TEST_F(ServerTest, GetRangeWithZeroToInfinite) {
|
||||||
auto res = cli_.Get("/with-range", {
|
auto res = cli_.Get("/with-range", Headers{
|
||||||
{"Range", "bytes=0-"},
|
{"Range", "bytes=0-"},
|
||||||
{"Accept-Encoding", ""},
|
{"Accept-Encoding", ""},
|
||||||
});
|
});
|
||||||
@ -3883,8 +3899,8 @@ TEST_F(ServerTest, GetRangeWithZeroToInfinite) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithRangeMultipart) {
|
TEST_F(ServerTest, GetStreamedWithRangeMultipart) {
|
||||||
auto res =
|
auto res = cli_.Get("/streamed-with-range",
|
||||||
cli_.Get("/streamed-with-range", {{make_range_header({{1, 2}, {4, 5}})}});
|
Headers{make_range_header({{1, 2}, {4, 5}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("267", res->get_header_value("Content-Length"));
|
EXPECT_EQ("267", res->get_header_value("Content-Length"));
|
||||||
@ -3898,8 +3914,8 @@ TEST_F(ServerTest, GetStreamedWithTooManyRanges) {
|
|||||||
ranges.emplace_back(0, -1);
|
ranges.emplace_back(0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res =
|
auto res = cli_.Get("/streamed-with-range?error",
|
||||||
cli_.Get("/streamed-with-range?error", {{make_range_header(ranges)}});
|
Headers{make_range_header(ranges)});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
||||||
@ -3909,7 +3925,7 @@ TEST_F(ServerTest, GetStreamedWithTooManyRanges) {
|
|||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithNonAscendingRanges) {
|
TEST_F(ServerTest, GetStreamedWithNonAscendingRanges) {
|
||||||
auto res = cli_.Get("/streamed-with-range?error",
|
auto res = cli_.Get("/streamed-with-range?error",
|
||||||
{{make_range_header({{0, -1}, {0, -1}})}});
|
Headers{make_range_header({{0, -1}, {0, -1}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
||||||
@ -3918,8 +3934,9 @@ TEST_F(ServerTest, GetStreamedWithNonAscendingRanges) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetStreamedWithRangesMoreThanTwoOverwrapping) {
|
TEST_F(ServerTest, GetStreamedWithRangesMoreThanTwoOverwrapping) {
|
||||||
auto res = cli_.Get("/streamed-with-range?error",
|
auto res =
|
||||||
{{make_range_header({{0, 1}, {1, 2}, {2, 3}, {3, 4}})}});
|
cli_.Get("/streamed-with-range?error",
|
||||||
|
Headers{make_range_header({{0, 1}, {1, 2}, {2, 3}, {3, 4}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
EXPECT_EQ("0", res->get_header_value("Content-Length"));
|
||||||
@ -3969,7 +3986,7 @@ TEST_F(ServerTest, ClientStop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetWithRange1) {
|
TEST_F(ServerTest, GetWithRange1) {
|
||||||
auto res = cli_.Get("/with-range", {
|
auto res = cli_.Get("/with-range", Headers{
|
||||||
make_range_header({{3, 5}}),
|
make_range_header({{3, 5}}),
|
||||||
{"Accept-Encoding", ""},
|
{"Accept-Encoding", ""},
|
||||||
});
|
});
|
||||||
@ -3982,7 +3999,7 @@ TEST_F(ServerTest, GetWithRange1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetWithRange2) {
|
TEST_F(ServerTest, GetWithRange2) {
|
||||||
auto res = cli_.Get("/with-range", {
|
auto res = cli_.Get("/with-range", Headers{
|
||||||
make_range_header({{1, -1}}),
|
make_range_header({{1, -1}}),
|
||||||
{"Accept-Encoding", ""},
|
{"Accept-Encoding", ""},
|
||||||
});
|
});
|
||||||
@ -3995,7 +4012,7 @@ TEST_F(ServerTest, GetWithRange2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetWithRange3) {
|
TEST_F(ServerTest, GetWithRange3) {
|
||||||
auto res = cli_.Get("/with-range", {
|
auto res = cli_.Get("/with-range", Headers{
|
||||||
make_range_header({{0, 0}}),
|
make_range_header({{0, 0}}),
|
||||||
{"Accept-Encoding", ""},
|
{"Accept-Encoding", ""},
|
||||||
});
|
});
|
||||||
@ -4008,7 +4025,7 @@ TEST_F(ServerTest, GetWithRange3) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetWithRange4) {
|
TEST_F(ServerTest, GetWithRange4) {
|
||||||
auto res = cli_.Get("/with-range", {
|
auto res = cli_.Get("/with-range", Headers{
|
||||||
make_range_header({{-1, 2}}),
|
make_range_header({{-1, 2}}),
|
||||||
{"Accept-Encoding", ""},
|
{"Accept-Encoding", ""},
|
||||||
});
|
});
|
||||||
@ -4021,13 +4038,15 @@ TEST_F(ServerTest, GetWithRange4) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetWithRangeOffsetGreaterThanContent) {
|
TEST_F(ServerTest, GetWithRangeOffsetGreaterThanContent) {
|
||||||
auto res = cli_.Get("/with-range", {{make_range_header({{10000, 20000}})}});
|
auto res =
|
||||||
|
cli_.Get("/with-range", Headers{make_range_header({{10000, 20000}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetWithRangeMultipart) {
|
TEST_F(ServerTest, GetWithRangeMultipart) {
|
||||||
auto res = cli_.Get("/with-range", {{make_range_header({{1, 2}, {4, 5}})}});
|
auto res =
|
||||||
|
cli_.Get("/with-range", Headers{make_range_header({{1, 2}, {4, 5}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
|
||||||
EXPECT_EQ("267", res->get_header_value("Content-Length"));
|
EXPECT_EQ("267", res->get_header_value("Content-Length"));
|
||||||
@ -4036,15 +4055,15 @@ TEST_F(ServerTest, GetWithRangeMultipart) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetWithRangeMultipartOffsetGreaterThanContent) {
|
TEST_F(ServerTest, GetWithRangeMultipartOffsetGreaterThanContent) {
|
||||||
auto res =
|
auto res = cli_.Get("/with-range",
|
||||||
cli_.Get("/with-range", {{make_range_header({{-1, 2}, {10000, 30000}})}});
|
Headers{make_range_header({{-1, 2}, {10000, 30000}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, GetWithRangeCustomizedResponse) {
|
TEST_F(ServerTest, GetWithRangeCustomizedResponse) {
|
||||||
auto res = cli_.Get("/with-range-customized-response",
|
auto res = cli_.Get("/with-range-customized-response",
|
||||||
{{make_range_header({{1, 2}})}});
|
Headers{make_range_header({{1, 2}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::BadRequest_400, res->status);
|
EXPECT_EQ(StatusCode::BadRequest_400, res->status);
|
||||||
EXPECT_EQ(true, res->has_header("Content-Length"));
|
EXPECT_EQ(true, res->has_header("Content-Length"));
|
||||||
@ -4054,7 +4073,7 @@ TEST_F(ServerTest, GetWithRangeCustomizedResponse) {
|
|||||||
|
|
||||||
TEST_F(ServerTest, GetWithRangeMultipartCustomizedResponseMultipleRange) {
|
TEST_F(ServerTest, GetWithRangeMultipartCustomizedResponseMultipleRange) {
|
||||||
auto res = cli_.Get("/with-range-customized-response",
|
auto res = cli_.Get("/with-range-customized-response",
|
||||||
{{make_range_header({{1, 2}, {4, 5}})}});
|
Headers{make_range_header({{1, 2}, {4, 5}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::BadRequest_400, res->status);
|
EXPECT_EQ(StatusCode::BadRequest_400, res->status);
|
||||||
EXPECT_EQ(true, res->has_header("Content-Length"));
|
EXPECT_EQ(true, res->has_header("Content-Length"));
|
||||||
@ -4063,7 +4082,7 @@ TEST_F(ServerTest, GetWithRangeMultipartCustomizedResponseMultipleRange) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, Issue1772) {
|
TEST_F(ServerTest, Issue1772) {
|
||||||
auto res = cli_.Get("/issue1772", {{make_range_header({{1000, -1}})}});
|
auto res = cli_.Get("/issue1772", Headers{make_range_header({{1000, -1}})});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
|
EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
|
||||||
}
|
}
|
||||||
@ -5766,7 +5785,7 @@ TEST(GetWithParametersTest, GetWithParameters) {
|
|||||||
params.emplace("hello", "world");
|
params.emplace("hello", "world");
|
||||||
params.emplace("hello2", "world2");
|
params.emplace("hello2", "world2");
|
||||||
params.emplace("hello3", "world3");
|
params.emplace("hello3", "world3");
|
||||||
auto res = cli.Get("/", params, Headers{});
|
auto res = cli.Get("/", params);
|
||||||
|
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
@ -5823,11 +5842,10 @@ TEST(GetWithParametersTest, GetWithParameters2) {
|
|||||||
params.emplace("hello", "world");
|
params.emplace("hello", "world");
|
||||||
|
|
||||||
std::string body;
|
std::string body;
|
||||||
auto res = cli.Get("/", params, Headers{},
|
auto res = cli.Get("/", params, [&](const char *data, size_t data_length) {
|
||||||
[&](const char *data, size_t data_length) {
|
body.append(data, data_length);
|
||||||
body.append(data, data_length);
|
return true;
|
||||||
return true;
|
});
|
||||||
});
|
|
||||||
|
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
@ -5849,7 +5867,7 @@ TEST(ClientDefaultHeadersTest, DefaultHeaders_Online) {
|
|||||||
Client cli(host);
|
Client cli(host);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cli.set_default_headers({make_range_header({{1, 10}})});
|
cli.set_default_headers(Headers{make_range_header({{1, 10}})});
|
||||||
cli.set_connection_timeout(5);
|
cli.set_connection_timeout(5);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -6669,7 +6687,7 @@ TEST(SendAPI, WithParamsInRequest) {
|
|||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto res = cli.Get("/", {{"test", "test_value"}}, Headers{});
|
auto res = cli.Get("/", Params{{"test", "test_value"}});
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6798,8 +6816,8 @@ TEST(YahooRedirectTest3, NewResultInterface_Online) {
|
|||||||
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
|
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
|
||||||
TEST(DecodeWithChunkedEncoding, BrotliEncoding_Online) {
|
TEST(DecodeWithChunkedEncoding, BrotliEncoding_Online) {
|
||||||
Client cli("https://cdnjs.cloudflare.com");
|
Client cli("https://cdnjs.cloudflare.com");
|
||||||
auto res =
|
auto res = cli.Get("/ajax/libs/jquery/3.5.1/jquery.js",
|
||||||
cli.Get("/ajax/libs/jquery/3.5.1/jquery.js", {{"Accept-Encoding", "br"}});
|
Headers{{"Accept-Encoding", "br"}});
|
||||||
|
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
@ -6828,7 +6846,7 @@ TEST(HttpsToHttpRedirectTest2, SimpleInterface_Online) {
|
|||||||
params.emplace("url", "http://www.google.com");
|
params.emplace("url", "http://www.google.com");
|
||||||
params.emplace("status_code", "302");
|
params.emplace("status_code", "302");
|
||||||
|
|
||||||
auto res = cli.Get("/httpbin/redirect-to", params, Headers{});
|
auto res = cli.Get("/httpbin/redirect-to", params);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
@ -6840,7 +6858,7 @@ TEST(HttpsToHttpRedirectTest3, SimpleInterface_Online) {
|
|||||||
Params params;
|
Params params;
|
||||||
params.emplace("url", "http://www.google.com");
|
params.emplace("url", "http://www.google.com");
|
||||||
|
|
||||||
auto res = cli.Get("/httpbin/redirect-to?status_code=302", params, Headers{});
|
auto res = cli.Get("/httpbin/redirect-to?status_code=302", params);
|
||||||
ASSERT_TRUE(res);
|
ASSERT_TRUE(res);
|
||||||
EXPECT_EQ(StatusCode::OK_200, res->status);
|
EXPECT_EQ(StatusCode::OK_200, res->status);
|
||||||
}
|
}
|
||||||
@ -7994,7 +8012,7 @@ TEST(DirtyDataRequestTest, HeadFieldValueContains_CR_LF_NUL) {
|
|||||||
svr.wait_until_ready();
|
svr.wait_until_ready();
|
||||||
|
|
||||||
Client cli(HOST, PORT);
|
Client cli(HOST, PORT);
|
||||||
cli.Get("/test", {{"Test", "_\n\r_\n\r_"}});
|
cli.Get("/test", Headers{{"Test", "_\n\r_\n\r_"}});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InvalidHeaderCharsTest, is_field_name) {
|
TEST(InvalidHeaderCharsTest, is_field_name) {
|
||||||
@ -8207,8 +8225,9 @@ TEST(Expect100ContinueTest, ServerClosesConnection) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename S, typename C>
|
TEST(MaxTimeoutTest, ContentStream) {
|
||||||
inline void max_timeout_test(S &svr, C &cli, time_t timeout, time_t threshold) {
|
Server svr;
|
||||||
|
|
||||||
svr.Get("/stream", [&](const Request &, Response &res) {
|
svr.Get("/stream", [&](const Request &, Response &res) {
|
||||||
auto data = new std::string("01234567890123456789");
|
auto data = new std::string("01234567890123456789");
|
||||||
|
|
||||||
@ -8278,6 +8297,10 @@ inline void max_timeout_test(S &svr, C &cli, time_t timeout, time_t threshold) {
|
|||||||
|
|
||||||
svr.wait_until_ready();
|
svr.wait_until_ready();
|
||||||
|
|
||||||
|
const time_t timeout = 2000;
|
||||||
|
const time_t threshold = 200;
|
||||||
|
|
||||||
|
Client cli("localhost", PORT);
|
||||||
cli.set_max_timeout(std::chrono::milliseconds(timeout));
|
cli.set_max_timeout(std::chrono::milliseconds(timeout));
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -8329,108 +8352,132 @@ inline void max_timeout_test(S &svr, C &cli, time_t timeout, time_t threshold) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MaxTimeoutTest, ContentStream) {
|
|
||||||
time_t timeout = 2000;
|
|
||||||
time_t threshold = 200;
|
|
||||||
|
|
||||||
Server svr;
|
|
||||||
Client cli("localhost", PORT);
|
|
||||||
max_timeout_test(svr, cli, timeout, threshold);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
TEST(MaxTimeoutTest, ContentStreamSSL) {
|
TEST(MaxTimeoutTest, ContentStreamSSL) {
|
||||||
time_t timeout = 2000;
|
|
||||||
time_t threshold = 500; // SSL_shutdown is slow on some operating systems.
|
|
||||||
|
|
||||||
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
|
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
|
||||||
|
|
||||||
SSLClient cli("localhost", PORT);
|
svr.Get("/stream", [&](const Request &, Response &res) {
|
||||||
cli.enable_server_certificate_verification(false);
|
auto data = new std::string("01234567890123456789");
|
||||||
|
|
||||||
max_timeout_test(svr, cli, timeout, threshold);
|
res.set_content_provider(
|
||||||
}
|
data->size(), "text/plain",
|
||||||
#endif
|
[&, data](size_t offset, size_t length, DataSink &sink) {
|
||||||
|
const size_t DATA_CHUNK_SIZE = 4;
|
||||||
class EventDispatcher {
|
const auto &d = *data;
|
||||||
public:
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
EventDispatcher() {}
|
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
|
||||||
|
return true;
|
||||||
void wait_event(DataSink *sink) {
|
},
|
||||||
unique_lock<mutex> lk(m_);
|
[data](bool success) {
|
||||||
int id = id_;
|
EXPECT_FALSE(success);
|
||||||
cv_.wait(lk, [&] { return cid_ == id; });
|
delete data;
|
||||||
sink->write(message_.data(), message_.size());
|
});
|
||||||
}
|
|
||||||
|
|
||||||
void send_event(const string &message) {
|
|
||||||
lock_guard<mutex> lk(m_);
|
|
||||||
cid_ = id_++;
|
|
||||||
message_ = message;
|
|
||||||
cv_.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutex m_;
|
|
||||||
condition_variable cv_;
|
|
||||||
atomic_int id_{0};
|
|
||||||
atomic_int cid_{-1};
|
|
||||||
string message_;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(ClientInThreadTest, Issue2068) {
|
|
||||||
EventDispatcher ed;
|
|
||||||
|
|
||||||
Server svr;
|
|
||||||
svr.Get("/event1", [&](const Request & /*req*/, Response &res) {
|
|
||||||
res.set_chunked_content_provider("text/event-stream",
|
|
||||||
[&](size_t /*offset*/, DataSink &sink) {
|
|
||||||
ed.wait_event(&sink);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto listen_thread = std::thread([&svr]() { svr.listen(HOST, PORT); });
|
svr.Get("/stream_without_length", [&](const Request &, Response &res) {
|
||||||
|
auto i = new size_t(0);
|
||||||
|
|
||||||
svr.wait_until_ready();
|
res.set_content_provider(
|
||||||
|
"text/plain",
|
||||||
thread event_thread([&] {
|
[i](size_t, DataSink &sink) {
|
||||||
int id = 0;
|
if (*i < 5) {
|
||||||
while (svr.is_running()) {
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
this_thread::sleep_for(chrono::milliseconds(500));
|
sink.write("abcd", 4);
|
||||||
|
(*i)++;
|
||||||
std::stringstream ss;
|
} else {
|
||||||
ss << "data: " << id << "\n\n";
|
sink.done();
|
||||||
ed.send_event(ss.str());
|
}
|
||||||
id++;
|
return true;
|
||||||
}
|
},
|
||||||
|
[i](bool success) {
|
||||||
|
EXPECT_FALSE(success);
|
||||||
|
delete i;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
svr.Get("/chunked", [&](const Request &, Response &res) {
|
||||||
|
auto i = new size_t(0);
|
||||||
|
|
||||||
|
res.set_chunked_content_provider(
|
||||||
|
"text/plain",
|
||||||
|
[i](size_t, DataSink &sink) {
|
||||||
|
if (*i < 5) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
sink.os << "abcd";
|
||||||
|
(*i)++;
|
||||||
|
} else {
|
||||||
|
sink.done();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[i](bool success) {
|
||||||
|
EXPECT_FALSE(success);
|
||||||
|
delete i;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
|
||||||
auto se = detail::scope_exit([&] {
|
auto se = detail::scope_exit([&] {
|
||||||
svr.stop();
|
svr.stop();
|
||||||
|
|
||||||
listen_thread.join();
|
listen_thread.join();
|
||||||
event_thread.join();
|
|
||||||
|
|
||||||
ASSERT_FALSE(svr.is_running());
|
ASSERT_FALSE(svr.is_running());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
svr.wait_until_ready();
|
||||||
|
|
||||||
|
const time_t timeout = 2000;
|
||||||
|
const time_t threshold = 1000; // SSL_shutdown is slow...
|
||||||
|
|
||||||
|
SSLClient cli("localhost", PORT);
|
||||||
|
cli.enable_server_certificate_verification(false);
|
||||||
|
cli.set_max_timeout(std::chrono::milliseconds(timeout));
|
||||||
|
|
||||||
{
|
{
|
||||||
auto client = detail::make_unique<Client>(HOST, PORT);
|
auto start = std::chrono::steady_clock::now();
|
||||||
client->set_read_timeout(std::chrono::minutes(10));
|
|
||||||
|
|
||||||
std::atomic<bool> stop{false};
|
auto res = cli.Get("/stream");
|
||||||
|
|
||||||
std::thread t([&] {
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
client->Get("/event1",
|
std::chrono::steady_clock::now() - start)
|
||||||
[&](const char *, size_t) -> bool { return !stop; });
|
.count();
|
||||||
|
|
||||||
|
ASSERT_FALSE(res);
|
||||||
|
EXPECT_EQ(Error::Read, res.error());
|
||||||
|
EXPECT_TRUE(timeout <= elapsed && elapsed < timeout + threshold)
|
||||||
|
<< "Timeout exceeded by " << (elapsed - timeout) << "ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto start = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
auto res = cli.Get("/stream_without_length");
|
||||||
|
|
||||||
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::steady_clock::now() - start)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
ASSERT_FALSE(res);
|
||||||
|
EXPECT_EQ(Error::Read, res.error());
|
||||||
|
EXPECT_TRUE(timeout <= elapsed && elapsed < timeout + threshold)
|
||||||
|
<< "Timeout exceeded by " << (elapsed - timeout) << "ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto start = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
auto res = cli.Get("/chunked", [&](const char *data, size_t data_length) {
|
||||||
|
EXPECT_EQ("abcd", string(data, data_length));
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
stop = true;
|
std::chrono::steady_clock::now() - start)
|
||||||
client->stop();
|
.count();
|
||||||
client.reset();
|
|
||||||
|
|
||||||
t.join();
|
ASSERT_FALSE(res);
|
||||||
|
EXPECT_EQ(Error::Read, res.error());
|
||||||
|
EXPECT_TRUE(timeout <= elapsed && elapsed < timeout + threshold)
|
||||||
|
<< "Timeout exceeded by " << (elapsed - timeout) << "ms";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user