Compare commits

..

28 Commits

Author SHA1 Message Date
yhirose 615867322d Fixed build errors and apply clangformat 2020-11-29 12:29:18 -05:00
David Wu 02d3cd5909 Fix multiple threading bugs including #699 and #697 2020-11-29 12:29:15 -05:00
yhirose 47e5af15ea Updated README 2020-11-22 09:22:40 -05:00
yhirose a5c239c174 Fix #765 2020-11-21 16:35:31 -05:00
yhirose c2afc5ca44 Added chunked content provider support on client 2020-11-21 08:46:50 -05:00
yhirose cee062d4c9 Fixed unit tests due to the change in #763 2020-11-19 21:04:46 -05:00
Unkorunk b21dc8cbe0 Fix incorrect content_encoding for Brotli (#763) 2020-11-19 12:39:20 -05:00
372046933 e1133a2dcb std::tolower is undefined if the argument's value is neither representable as unsigned char nor equal to EOF (#761)
Co-authored-by: taoxu <taoxu@bilibili.com>
2020-11-19 09:21:40 -05:00
yhirose e273fec93c Fixed Visual Studio setup 2020-11-19 09:17:59 -05:00
yhirose 95d0b073bd Fix #754 2020-11-15 08:13:08 -05:00
vawen 9c7d841b37 Fix: #746 Compile error under VS2015 (#747)
Co-authored-by: jigarcia@vaxtor.es <jigarcia@vaxtor.es>
2020-11-10 08:41:53 -05:00
yhirose f086bf5310 Fix #738 2020-11-08 18:16:23 -05:00
yhirose 6613d7b7ad Fixed warnings 2020-11-08 17:59:11 -05:00
yhirose 6adf130bf3 Fix #739 2020-11-07 21:54:47 -05:00
miketsts b6b2eaf5bc Add unit test SSLConnectTimeout (#741)
Add unit test for issue #682 fixed in PR #728, which does not contain
the test of its own.

The test creates a fake SSL server, inherited from SSLServer, which
does not create an SSL context. When an SSL client attempts to send it
a request, it gets a timeout error. Prior to PR #728, the client would
wait indefinitely

Co-authored-by: Michael Tseitlin <michael.tseitlin@concertio.com>
2020-11-07 09:41:20 -05:00
yhirose eb4b7c70a9 Fix #737 2020-11-07 09:33:22 -05:00
yhirose 84661ea6ed Refactoring 2020-11-05 07:06:53 -05:00
yhirose 041122908c Fix problem with invalid range 2020-11-05 00:20:59 -05:00
yhirose 401de608df Fixed debug option problem. 2020-11-05 00:20:59 -05:00
yhirose 726c64cf10 Code format 2020-11-05 00:20:59 -05:00
Omkar Jadhav e1f781a21a [oss-fuzz] Enable msan for fuzz tests (#734)
* Disable openssl as we're not using it in fuzz tests

* Increase timeout in ClientStop test
2020-11-04 11:30:56 -05:00
Omkar Jadhav 72b81badad Fix issues reported by oss-fuzz (#729)
* Fix oss-fuzz issue #26529

* Add test for oss-fuzz issue  #26598

* Fix oss-fuzz issue  #26632

* Revert change and add new test cases
2020-11-03 11:36:02 -05:00
yhirose 17428a8fbf Fixed warning 2020-11-03 09:16:28 -05:00
Daniel Ottiger 6e1879dfae ssl-verify-host: fix verifying ip addresses containing zero's (#732)
* ssl-verify-host: fix verifying ip addresses containing zero's

If the subject alternate name contained an ip address with an zero
(like 10.42.0.1) it could not successfully verify.
It is because in c++ strings are null-terminated
and therefore strlen(name) would return a wrong result.
As I can not see why we can not trust the length returned by openssl,
lets drop this check.

* ssl-verify-host: add test case

lets try to validate against 127.0.0.1

Co-authored-by: Daniel Ottiger <daniel.ottiger@ch.schindler.com>
2020-11-02 20:27:34 -05:00
miketsts eb1d2e04bc SSL_connect and SSL_accept in non-blocking mode (#728)
SSL connection is performed in two steps:
First, a regular socket connection is established.
Then, SSL_connect/SSL_accept is called to establish SSL handshake.

If a network problem occurs during the second stage, SSL_connect on
the client may hang indefinitely.

The non-blocking mode solves this problem.

Co-authored-by: Michael Tseitlin <michael.tseitlin@concertio.com>
2020-11-02 17:05:08 -05:00
yhirose c909ffa758 Fix #731 2020-11-01 21:03:47 -05:00
yhirose ff5677ad19 Updated README 2020-10-27 20:35:56 -04:00
yhirose 8b1b31ac20 Fix #723 2020-10-27 20:32:19 -04:00
8 changed files with 975 additions and 354 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
run: cd test && make -f Makefile.fuzz_test
- name: setup msbuild on windows
if: matrix.os == 'windows-latest'
uses: warrenbuckley/Setup-MSBuild@v1
uses: microsoft/setup-msbuild@v1.0.2
- name: make-windows
if: matrix.os == 'windows-latest'
run: |
+43 -1
View File
@@ -365,6 +365,27 @@ httplib::Client cli("http://localhost:8080");
httplib::Client cli("https://localhost");
```
### Error code
Here is the list of errors from `Result::error()`.
```c++
enum Error {
Success = 0,
Unknown,
Connection,
BindIPAddress,
Read,
Write,
ExceedRedirectCount,
Canceled,
SSLConnection,
SSLLoadingCerts,
SSLServerVerification,
UnsupportedMultipartBoundaryChars
};
```
### GET with HTTP headers
```c++
@@ -481,7 +502,7 @@ auto res = cli.Get(
```cpp
std::string body = ...;
auto res = cli_.Post(
auto res = cli.Post(
"/stream", body.size(),
[](size_t offset, size_t length, DataSink &sink) {
sink.write(body.data() + offset, length);
@@ -490,6 +511,21 @@ auto res = cli_.Post(
"text/plain");
```
### Chunked transfer encoding
```cpp
auto res = cli.Post(
"/stream",
[](size_t offset, DataSink &sink) {
sink.os << "chunked data 1";
sink.os << "chunked data 2";
sink.os << "chunked data 3";
sink.done();
return true; // return 'false' if you want to cancel the request.
},
"text/plain");
```
### With Progress Callback
```cpp
@@ -609,6 +645,12 @@ cli.set_ca_cert_path("./ca-bundle.crt");
cli.enable_server_certificate_verification(true);
```
Note: When using SSL, it seems impossible to avoid SIGPIPE in all cases, since on some operating systems, SIGPIPE
can only be suppressed on a per-message basis, but there is no way to make the OpenSSL library do so for its
internal communications. If your program needs to avoid being terminated on SIGPIPE, the only fully general way might
be to set up a signal handler for SIGPIPE to handle or ignore it yourself.
Compression
-----------
+708 -325
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -1,5 +1,5 @@
#CXX = clang++
CXXFLAGS = -ggdb -O0 -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits -Wconversion #-fsanitize=address
CXXFLAGS = -g -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits -Wconversion #-fsanitize=address
OPENSSL_DIR = /usr/local/opt/openssl@1.1
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
@@ -24,6 +24,7 @@ test_proxy : test_proxy.cc ../httplib.h Makefile cert.pem
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
+2 -1
View File
@@ -19,7 +19,8 @@ all : server_fuzzer
# Fuzz target, so that you can choose which $(LIB_FUZZING_ENGINE) to use.
server_fuzzer : server_fuzzer.cc ../../httplib.h
$(CXX) $(CXXFLAGS) -o $@ $< -Wl,-Bstatic $(OPENSSL_SUPPORT) -Wl,-Bdynamic -ldl $(ZLIB_SUPPORT) $(LIB_FUZZING_ENGINE) -pthread
# $(CXX) $(CXXFLAGS) -o $@ $< -Wl,-Bstatic $(OPENSSL_SUPPORT) -Wl,-Bdynamic -ldl $(ZLIB_SUPPORT) $(LIB_FUZZING_ENGINE) -pthread
$(CXX) $(CXXFLAGS) -o $@ $< $(ZLIB_SUPPORT) $(LIB_FUZZING_ENGINE) -pthread
zip -q -r server_fuzzer_seed_corpus.zip corpus
clean:
+2
View File
@@ -35,6 +35,8 @@ class FuzzedStream : public httplib::Stream {
port = 8080;
}
socket_t socket() const override { return 0; }
private:
const uint8_t* data_;
size_t size_;
+214 -25
View File
@@ -5,8 +5,10 @@
#include <chrono>
#include <future>
#include <thread>
#include <atomic>
#define SERVER_CERT_FILE "./cert.pem"
#define SERVER_CERT2_FILE "./cert2.pem"
#define SERVER_PRIVATE_KEY_FILE "./key.pem"
#define CA_CERT_FILE "./ca-bundle.crt"
#define CLIENT_CA_CERT_FILE "./rootCA.cert.pem"
@@ -134,6 +136,17 @@ TEST(GetHeaderValueTest, RegularValue) {
EXPECT_STREQ("text/html", val);
}
TEST(GetHeaderValueTest, SetContent) {
Response res;
res.set_content("html", "text/html");
EXPECT_EQ("text/html", res.get_header_value("Content-Type"));
res.set_content("text", "text/plain");
EXPECT_EQ(1, res.get_header_value_count("Content-Type"));
EXPECT_EQ("text/plain", res.get_header_value("Content-Type"));
}
TEST(GetHeaderValueTest, RegularValueInt) {
Headers headers = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
auto val =
@@ -766,6 +779,7 @@ TEST(YahooRedirectTest, Redirect) {
res = cli.Get("/");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("https://yahoo.com/", res->location);
}
#if 0
@@ -829,7 +843,7 @@ TEST(UrlWithSpace, Redirect) {
}
#endif
TEST(Server, BindDualStack) {
TEST(BindServerTest, BindDualStack) {
Server svr;
svr.Get("/1", [&](const Request & /*req*/, Response &res) {
@@ -862,7 +876,7 @@ TEST(Server, BindDualStack) {
ASSERT_FALSE(svr.is_running());
}
TEST(Server, BindAndListenSeparately) {
TEST(BindServerTest, BindAndListenSeparately) {
Server svr;
int port = svr.bind_to_any_port("0.0.0.0");
ASSERT_TRUE(svr.is_valid());
@@ -871,7 +885,7 @@ TEST(Server, BindAndListenSeparately) {
}
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
TEST(SSLServer, BindAndListenSeparately) {
TEST(BindServerTest, BindAndListenSeparatelySSL) {
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE,
CLIENT_CA_CERT_DIR);
int port = svr.bind_to_any_port("0.0.0.0");
@@ -881,6 +895,41 @@ TEST(SSLServer, BindAndListenSeparately) {
}
#endif
TEST(ErrorHandlerTest, ContentLength) {
Server svr;
svr.set_error_handler([](const Request & /*req*/, Response &res) {
res.status = 200;
res.set_content("abcdefghijklmnopqrstuvwxyz",
"text/html"); // <= Content-Length still 13
});
svr.Get("/hi", [](const Request & /*req*/, Response &res) {
res.set_content("Hello World!\n", "text/plain");
res.status = 524;
});
auto thread = std::thread([&]() { svr.listen(HOST, PORT); });
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
{
Client cli(HOST, PORT);
auto res = cli.Get("/hi");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
EXPECT_EQ("26", res->get_header_value("Content-Length"));
EXPECT_EQ("abcdefghijklmnopqrstuvwxyz", res->body);
}
svr.stop();
thread.join();
ASSERT_FALSE(svr.is_running());
}
class ServerTest : public ::testing::Test {
protected:
ServerTest()
@@ -1387,6 +1436,7 @@ TEST_F(ServerTest, GetMethod302Redirect) {
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("Hello World!", res->body);
EXPECT_EQ("/hi", res->location);
}
TEST_F(ServerTest, GetMethod404) {
@@ -1615,6 +1665,7 @@ TEST_F(ServerTest, PostMethod303Redirect) {
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("redirected.", res->body);
EXPECT_EQ("/2", res->location);
}
TEST_F(ServerTest, UserDefinedMIMETypeMapping) {
@@ -1898,9 +1949,7 @@ TEST_F(ServerTest, GetStreamedWithRange2) {
}
TEST_F(ServerTest, GetStreamedWithRangeSuffix1) {
auto res = cli_.Get("/streamed-with-range", {
{"Range", "bytes=-3"}
});
auto res = cli_.Get("/streamed-with-range", {{"Range", "bytes=-3"}});
ASSERT_TRUE(res);
EXPECT_EQ(206, res->status);
EXPECT_EQ("3", res->get_header_value("Content-Length"));
@@ -1908,11 +1957,8 @@ TEST_F(ServerTest, GetStreamedWithRangeSuffix1) {
EXPECT_EQ(std::string("efg"), res->body);
}
TEST_F(ServerTest, GetStreamedWithRangeSuffix2) {
auto res = cli_.Get("/streamed-with-range", {
{"Range", "bytes=-9999"}
});
auto res = cli_.Get("/streamed-with-range", {{"Range", "bytes=-9999"}});
ASSERT_TRUE(res);
EXPECT_EQ(206, res->status);
EXPECT_EQ("7", res->get_header_value("Content-Length"));
@@ -1920,15 +1966,23 @@ TEST_F(ServerTest, GetStreamedWithRangeSuffix2) {
EXPECT_EQ(std::string("abcdefg"), res->body);
}
TEST_F(ServerTest, GetStreamedWithRangeError) {
auto res = cli_.Get("/streamed-with-range", {
{"Range", "bytes=92233720368547758079223372036854775806-92233720368547758079223372036854775807"}
});
auto res = cli_.Get("/streamed-with-range",
{{"Range", "bytes=92233720368547758079223372036854775806-"
"92233720368547758079223372036854775807"}});
ASSERT_TRUE(res);
EXPECT_EQ(416, res->status);
}
TEST_F(ServerTest, GetRangeWithMaxLongLength) {
auto res =
cli_.Get("/with-range", {{"Range", "bytes=0-9223372036854775807"}});
EXPECT_EQ(206, res->status);
EXPECT_EQ("7", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("abcdefg"), res->body);
}
TEST_F(ServerTest, GetStreamedWithRangeMultipart) {
auto res =
cli_.Get("/streamed-with-range", {{make_range_header({{1, 2}, {4, 5}})}});
@@ -1964,8 +2018,7 @@ TEST_F(ServerTest, ClientStop) {
}));
}
std::this_thread::sleep_for(std::chrono::seconds(1));
std::this_thread::sleep_for(std::chrono::seconds(2));
while (cli_.is_socket_open()) {
cli_.stop();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
@@ -2011,6 +2064,12 @@ TEST_F(ServerTest, GetWithRange4) {
EXPECT_EQ(std::string("fg"), res->body);
}
TEST_F(ServerTest, GetWithRangeOffsetGreaterThanContent) {
auto res = cli_.Get("/with-range", {{make_range_header({{10000, 20000}})}});
ASSERT_TRUE(res);
EXPECT_EQ(416, res->status);
}
TEST_F(ServerTest, GetWithRangeMultipart) {
auto res = cli_.Get("/with-range", {{make_range_header({{1, 2}, {4, 5}})}});
ASSERT_TRUE(res);
@@ -2020,6 +2079,13 @@ TEST_F(ServerTest, GetWithRangeMultipart) {
EXPECT_EQ(269, res->body.size());
}
TEST_F(ServerTest, GetWithRangeMultipartOffsetGreaterThanContent) {
auto res =
cli_.Get("/with-range", {{make_range_header({{-1, 2}, {10000, 30000}})}});
ASSERT_TRUE(res);
EXPECT_EQ(416, res->status);
}
TEST_F(ServerTest, GetStreamedChunked) {
auto res = cli_.Get("/streamed-chunked");
ASSERT_TRUE(res);
@@ -2155,6 +2221,31 @@ TEST_F(ServerTest, PostWithContentProviderAbort) {
EXPECT_EQ(Error::Canceled, res.error());
}
TEST_F(ServerTest, PutWithContentProviderWithoutLength) {
auto res = cli_.Put(
"/put",
[](size_t /*offset*/, DataSink &sink) {
EXPECT_TRUE(sink.is_writable());
sink.os << "PUT";
sink.done();
return true;
},
"text/plain");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("PUT", res->body);
}
TEST_F(ServerTest, PostWithContentProviderWithoutLengthAbort) {
auto res = cli_.Post(
"/post", [](size_t /*offset*/, DataSink & /*sink*/) { return false; },
"text/plain");
ASSERT_TRUE(!res);
EXPECT_EQ(Error::Canceled, res.error());
}
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
TEST_F(ServerTest, PutWithContentProviderWithGzip) {
cli_.set_compress(true);
@@ -2185,6 +2276,33 @@ TEST_F(ServerTest, PostWithContentProviderWithGzipAbort) {
EXPECT_EQ(Error::Canceled, res.error());
}
TEST_F(ServerTest, PutWithContentProviderWithoutLengthWithGzip) {
cli_.set_compress(true);
auto res = cli_.Put(
"/put",
[](size_t /*offset*/, DataSink &sink) {
EXPECT_TRUE(sink.is_writable());
sink.os << "PUT";
sink.done();
return true;
},
"text/plain");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("PUT", res->body);
}
TEST_F(ServerTest, PostWithContentProviderWithoutLengthWithGzipAbort) {
cli_.set_compress(true);
auto res = cli_.Post(
"/post", [](size_t /*offset*/, DataSink & /*sink*/) { return false; },
"text/plain");
ASSERT_TRUE(!res);
EXPECT_EQ(Error::Canceled, res.error());
}
TEST_F(ServerTest, PutLargeFileWithGzip) {
cli_.set_compress(true);
auto res = cli_.Put("/put-large", LARGE_DATA, "text/plain");
@@ -2272,7 +2390,7 @@ TEST(GzipDecompressor, ChunkedDecompression) {
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
TEST_F(ServerTest, GetStreamedChunkedWithBrotli) {
Headers headers;
headers.emplace("Accept-Encoding", "brotli");
headers.emplace("Accept-Encoding", "br");
auto res = cli_.Get("/streamed-chunked", headers);
ASSERT_TRUE(res);
@@ -2282,7 +2400,7 @@ TEST_F(ServerTest, GetStreamedChunkedWithBrotli) {
TEST_F(ServerTest, GetStreamedChunkedWithBrotli2) {
Headers headers;
headers.emplace("Accept-Encoding", "brotli");
headers.emplace("Accept-Encoding", "br");
auto res = cli_.Get("/streamed-chunked2", headers);
ASSERT_TRUE(res);
@@ -2631,7 +2749,7 @@ TEST_F(ServerTest, Brotli) {
auto res = cli_.Get("/compress", headers);
ASSERT_TRUE(res);
EXPECT_EQ("brotli", res->get_header_value("Content-Encoding"));
EXPECT_EQ("br", res->get_header_value("Content-Encoding"));
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
EXPECT_EQ("19", res->get_header_value("Content-Length"));
EXPECT_EQ("123456789012345678901234567890123456789012345678901234567890123456"
@@ -2644,7 +2762,7 @@ TEST_F(ServerTest, Brotli) {
// Sends a raw request to a server listening at HOST:PORT.
static bool send_request(time_t read_timeout_sec, const std::string &req,
std::string *resp = nullptr) {
Error error = Error::Success;
std::atomic<Error> error(Error::Success);
auto client_sock =
detail::create_client_socket(HOST, PORT, false, nullptr,
@@ -3037,9 +3155,7 @@ TEST(KeepAliveTest, ReadTimeoutSSL) {
res.set_content("b", "text/plain");
});
auto listen_thread = std::thread([&svr]() {
svr.listen("localhost", PORT);
});
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
while (!svr.is_running()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
@@ -3245,6 +3361,31 @@ TEST(SSLClientTest, ServerCertificateVerification3) {
ASSERT_EQ(301, res->status);
}
TEST(SSLClientTest, ServerCertificateVerification4) {
SSLServer svr(SERVER_CERT2_FILE, SERVER_PRIVATE_KEY_FILE);
ASSERT_TRUE(svr.is_valid());
svr.Get("/test", [&](const Request &, Response &res) {
res.set_content("test", "text/plain");
svr.stop();
ASSERT_TRUE(true);
});
thread t = thread([&]() { ASSERT_TRUE(svr.listen("127.0.0.1", PORT)); });
std::this_thread::sleep_for(std::chrono::milliseconds(1));
SSLClient cli("127.0.0.1", PORT);
cli.set_ca_cert_path(SERVER_CERT2_FILE);
cli.enable_server_certificate_verification(true);
cli.set_connection_timeout(30);
auto res = cli.Get("/test");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
t.join();
}
TEST(SSLClientTest, WildcardHostNameMatch) {
SSLClient cli("www.youtube.com");
@@ -3420,6 +3561,51 @@ TEST(SSLClientServerTest, TrustDirOptional) {
t.join();
}
TEST(SSLClientServerTest, SSLConnectTimeout) {
class NoListenSSLServer : public SSLServer {
public:
NoListenSSLServer(const char *cert_path, const char *private_key_path,
const char *client_ca_cert_file_path,
const char *client_ca_cert_dir_path = nullptr)
: SSLServer(cert_path, private_key_path, client_ca_cert_file_path,
client_ca_cert_dir_path),
stop_(false) {}
bool stop_;
private:
bool process_and_close_socket(socket_t /*sock*/) override {
// Don't create SSL context
while (!stop_) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return true;
}
};
NoListenSSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE,
CLIENT_CA_CERT_FILE);
ASSERT_TRUE(svr.is_valid());
svr.Get("/test", [&](const Request &, Response &res) {
res.set_content("test", "text/plain");
});
thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
std::this_thread::sleep_for(std::chrono::milliseconds(1));
SSLClient cli(HOST, PORT, CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE);
cli.enable_server_certificate_verification(false);
cli.set_connection_timeout(1);
auto res = cli.Get("/test");
ASSERT_TRUE(!res);
EXPECT_EQ(Error::SSLConnection, res.error());
svr.stop_ = true;
svr.stop();
t.join();
}
#endif
#ifdef _WIN32
@@ -3456,6 +3642,7 @@ TEST(YahooRedirectTest2, SimpleInterface) {
res = cli.Get("/");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("https://yahoo.com/", res->location);
}
TEST(YahooRedirectTest3, SimpleInterface) {
@@ -3469,6 +3656,7 @@ TEST(YahooRedirectTest3, SimpleInterface) {
res = cli.Get("/");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("https://www.yahoo.com/", res->location);
}
TEST(YahooRedirectTest3, NewResultInterface) {
@@ -3492,13 +3680,14 @@ TEST(YahooRedirectTest3, NewResultInterface) {
EXPECT_EQ(200, res.value().status);
EXPECT_EQ(200, (*res).status);
EXPECT_EQ(200, res->status);
EXPECT_EQ("https://www.yahoo.com/", res->location);
}
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
TEST(DecodeWithChunkedEncoding, BrotliEncoding) {
Client cli("https://cdnjs.cloudflare.com");
auto res = cli.Get("/ajax/libs/jquery/3.5.1/jquery.js",
{{"Accept-Encoding", "brotli"}});
auto res =
cli.Get("/ajax/libs/jquery/3.5.1/jquery.js", {{"Accept-Encoding", "br"}});
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
+3
View File
@@ -16,3 +16,6 @@ emailAddress = test@email.address
[req_attributes]
challengePassword = 1234
[SAN]
subjectAltName=IP:127.0.0.1