Compare commits

...

76 Commits

Author SHA1 Message Date
yhirose dcdb0d047b Fixed PRI request problem 2019-10-03 13:44:18 -04:00
yhirose 1f86e41d97 Changed back to select as default 2019-10-03 13:44:18 -04:00
yhirose 6d8302313c Fixed warning 2019-10-03 13:44:18 -04:00
yhirose 89440ec322 Merge pull request #232 from sux2mfgj/fix_the_invalidhost_test
Fix a test, ConnectionErrorTest::InvalidPort.
2019-10-03 13:43:48 -04:00
yhirose 5edf455d72 Merge pull request #231 from sux2mfgj/fix_the_sample
Fix a sample code of multipart/form-data POST data in the README.md.
2019-10-03 13:42:31 -04:00
Shunsuke Mie 5f49c13f95 Fix a test, ConnectionErrorTest::InvalidPort. currently, the abcde.com is valid, so I change it. The first byte doesn't permit a hyphen. 2019-10-03 21:49:11 +09:00
Shunsuke Mie 760bccc3ad fix a sample code of multipart/form-data POST data in README.md. 2019-10-03 21:23:10 +09:00
yhirose a99e02aeb3 Add HTTP/2 Connection Preface check test 2019-10-01 06:28:45 -04:00
yhirose 4aae1dcc42 Merge pull request #224 from Zefz/configuration
Allow configuration to be overriden without source editing
2019-09-30 17:07:21 -04:00
Johan Jansen f23f9a06a9 Allow configuration to be overriden without source editing 2019-09-30 22:00:17 +02:00
yhirose 46466b1e28 Merge pull request #227 from ha11owed/master
Don't exit if accept fails due to no more file descriptors
2019-09-30 07:47:27 -04:00
Alin Gherman 224119a60a Retry in case of too many sockets opened instead of stopping the server. 2019-09-30 11:48:02 +02:00
yhirose c02849e269 Removed CPPHTTPLIB_USE_POLL, added CPPHTTPLIB_USE_SELECT 2019-09-29 19:43:22 -04:00
yhirose 71979b1e88 Merge pull request #226 from Zefz/mingw-compile-fix
Fix compilation on Mingw-64
2019-09-27 17:29:33 -04:00
yhirose a62d1f79f4 Merge pull request #225 from TangHuaiZhe/master
Fix compile error in android ndk
2019-09-27 17:29:07 -04:00
zefz b14b7b0f8f Fix compilation on Mingw-64 2019-09-27 20:23:16 +02:00
Tang Huaizhe 9dbe0d855c Fix compile error in android ndk 2019-09-27 13:32:23 +08:00
yhirose 2cef8df6ae Merge pull request #223 from Zefz/cpp-style-cast
Fix several -Wold-style-cast warnings in Clang-9
2019-09-26 19:00:45 -04:00
Johan Jansen 94fc229c44 Add missing explicit const_cast 2019-09-26 22:20:33 +02:00
Johan Jansen a7052cba22 Fix several -Wold-style-cast warnings in Clang-9 2019-09-26 22:03:18 +02:00
yhirose c47c6b3910 Updated test.vcxproj 2019-09-26 13:20:53 -04:00
yhirose c946eb7699 Fixed warnings on Windows 2019-09-26 08:13:20 -04:00
yhirose 1f99ad5d6e Updated vcxproj for test 2019-09-25 08:16:15 -04:00
yhirose 96e372bad2 Changed test.yaml to use actions/checkout@v1 2019-09-20 01:07:09 -04:00
yhirose fc56f39d17 Fixed Github Actions badge problem 2019-09-20 00:43:02 -04:00
yhirose 5844432a7b Add badge for Github Actions 2019-09-20 00:31:26 -04:00
yhirose b97420f363 Add test.yaml 2019-09-20 00:01:05 -04:00
yhirose 81610ee080 Merge pull request #218 from p0lloloco/master
Add ssl_context member function to SSLClient
2019-09-18 23:08:14 -04:00
PolloLoco c7f8561472 Added ssl_context member function to SSLClient in
order to allow access to the SSL_CTX struct, for
example to load the windows cert store
2019-09-18 15:10:15 +02:00
yhirose 47bc7456d2 Merge pull request #217 from yhirose/poll
Use 'poll' instead of 'select'
2019-09-18 08:46:20 -04:00
yhirose 4ab9270660 Use 'poll' as default instead of select (Fix #215) 2019-09-18 08:42:18 -04:00
yhirose d599a36c2a Format code 2019-09-16 17:48:17 -04:00
yhirose 6f8f51496d Merge branch 'gulrak-feature-response-handler-with-content-receiver' 2019-09-15 09:17:26 -04:00
yhirose 0c293887d0 Fixed problem with redirect 2019-09-15 09:15:21 -04:00
Steffen Schuemann 7e92ffec48 Added new Client::Get variant that combines a ContentReceiver with a new ResponseHandler
While trying to implement streaming of internet radio, where a ContentReceiver is needed to handle the audio data, I had the problem, that important information about the stream data is part of the HTTP header (e.g. size of audio chunks between meta data), so I added a ResponseHandler and a new Get variant, to gain access to the header before handling the first chunk of data.

The ResponseHandler can abort the request by returning false, in the same way as the ContentReceiver.

A test case was also added.
2019-09-14 14:55:12 +02:00
yhirose 531708816a Update README 2019-09-06 18:29:22 -04:00
yhirose bfec81998b Code cleanup 2019-09-06 18:16:42 -04:00
yhirose c9238434e1 Added redirect support (Fix #211) 2019-09-06 18:07:35 -04:00
yhirose e2babf315c Fixed build error on Windows 2019-09-05 13:22:44 -04:00
yhirose c434d555bb Fixed problem caused by former changes 2019-09-03 17:19:58 -04:00
yhirose 359b06681b Fixed warnings 2019-09-03 17:16:16 -04:00
yhirose a0fe91e84d Fixed unit test problem 2019-09-03 17:16:07 -04:00
yhirose 80f040cf69 Fix #209 2019-09-03 17:10:04 -04:00
yhirose 037b4fc789 Fixed problem with keep-alive on client 2019-09-03 17:05:10 -04:00
yhirose a782d1b609 Added OpenSSL version check. (Currently commented out) 2019-08-31 20:15:50 -04:00
yhirose 6a03ddf912 Update README 2019-08-31 18:01:45 -04:00
yhirose 1e82359329 Keep-alive connection support on client (Fix #36) 2019-08-31 17:52:24 -04:00
yhirose a4160e6ac1 Fix #212 2019-08-25 17:19:20 -04:00
yhirose bdbfc6cfe7 Fix #210 2019-08-25 16:49:10 -04:00
yhirose 22615f9682 Fix #203 2019-08-07 06:34:24 -04:00
yhirose 64991a560a Fixed problems with Win32 build 2019-08-07 15:21:22 +09:00
yhirose d7bb402ca7 Format code 2019-08-06 18:12:05 +09:00
yhirose d58deddbcc Fixed #198 2019-08-06 18:10:41 +09:00
yhirose 3629f87627 Fixed thread pool problem. 2019-08-06 08:31:43 +09:00
yhirose 1b95bf8cc3 Updated README 2019-08-05 18:24:30 +09:00
yhirose e383b277a4 Updated README 2019-08-05 18:17:40 +09:00
yhirose bf541442ea Updated README 2019-08-05 10:51:27 +09:00
yhirose 2823a94fc1 Added 'resource_releaser' for content provider 2019-08-05 09:40:23 +09:00
yhirose 5a13539e57 Revert "Fixed unit test error on Windows"
This reverts commit 531f6ab84d.
2019-08-04 09:50:47 +09:00
yhirose 531f6ab84d Fixed unit test error on Windows 2019-08-03 20:43:27 -04:00
yhirose f4aaba6362 Fixed warnings on Windows 2019-08-03 20:43:15 -04:00
yhirose c899462e75 Added 'Content-Range' header for single range request 2019-08-03 22:12:24 +09:00
yhirose 9785cd47f2 Thread pool support 2019-08-03 16:39:39 +09:00
yhirose 579ff1a0a6 new_task_queue support 2019-08-03 13:15:05 +09:00
yhirose 47312e6df9 Added TaskQueue interface 2019-08-03 12:11:22 +09:00
yhirose 66b81a1497 Code cleanup 2019-08-03 10:47:48 +09:00
yhirose 9d7b717504 Range header support and redesign of content provider interface 2019-08-03 03:28:39 +09:00
yhirose 3291bdad91 Fixed a build error with example/redirect.cc 2019-08-03 03:28:38 +09:00
yhirose e8799383f3 Made unit tests stable 2019-07-30 01:51:53 +00:00
yhirose 58f72bc8b6 Code cleanup 2019-07-29 14:24:40 -04:00
yhirose 4c58b91e40 Added additonal status messages 2019-07-29 09:47:50 -04:00
yhirose 06b3dee5aa Code cleanup 2019-07-28 19:12:44 -04:00
yhirose ba7f9fe4c3 Added more unit tests 2019-07-28 19:11:58 -04:00
yhirose 8480850a3f Fixed build error 2019-07-28 19:09:24 -04:00
yhirose d15df874b3 Code cleanup 2019-07-28 07:52:57 -04:00
yhirose f40de531ab Fix #196 2019-07-26 14:39:09 -04:00
7 changed files with 1740 additions and 425 deletions
+17
View File
@@ -0,0 +1,17 @@
name: test
on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macOS-latest, ubuntu-latest]
steps:
- name: checkout
uses: actions/checkout@v1
- name: make
run: cd test && make
+123 -7
View File
@@ -1,6 +1,7 @@
cpp-httplib
===========
[![](https://github.com/yhirose/cpp-httplib/workflows/test/badge.svg)](https://github.com/yhirose/cpp-httplib/actions)
[![Build Status](https://travis-ci.org/yhirose/cpp-httplib.svg?branch=master)](https://travis-ci.org/yhirose/cpp-httplib)
[![Bulid Status](https://ci.appveyor.com/api/projects/status/github/yhirose/cpp-httplib?branch=master&svg=true)](https://ci.appveyor.com/project/yhirose/cpp-httplib)
@@ -76,12 +77,86 @@ svr.set_error_handler([](const auto& req, auto& res) {
```cpp
svr.Post("/multipart", [&](const auto& req, auto& res) {
auto size = req.files.size();
auto ret = req.has_file("name1"));
auto ret = req.has_file("name1");
const auto& file = req.get_file_value("name1");
// file.filename;
// file.content_type;
auto body = req.body.substr(file.offset, file.length));
})
auto body = req.body.substr(file.offset, file.length);
});
```
### Stream content with Content provider
```cpp
const uint64_t DATA_CHUNK_SIZE = 4;
svr.Get("/stream", [&](const Request &req, Response &res) {
auto data = new std::string("abcdefg");
res.set_content_provider(
data->size(), // Content length
[data](uint64_t offset, uint64_t length, Out out) {
const auto &d = *data;
out(&d[offset], std::min(length, DATA_CHUNK_SIZE));
},
[data] { delete data; });
});
```
### Chunked transfer encoding
```cpp
svr.Get("/chunked", [&](const Request& req, Response& res) {
res.set_chunked_content_provider(
[](uint64_t offset, Out out, Done done) {
out("123", 3);
out("345", 3);
out("789", 3);
done();
}
);
});
```
### Default thread pool supporet
Set thread count to 8:
```cpp
#define CPPHTTPLIB_THREAD_POOL_COUNT 8
```
Disable the default thread pool:
```cpp
#define CPPHTTPLIB_THREAD_POOL_COUNT 0
```
### Override the default thread pool with yours
```cpp
class YourThreadPoolTaskQueue : public TaskQueue {
public:
YourThreadPoolTaskQueue(size_t n) {
pool_.start_with_thread_count(n);
}
virtual void enqueue(std::function<void()> fn) override {
pool_.enqueue(fn);
}
virtual void shutdown() override {
pool_.shutdown_gracefully();
}
private:
YourThreadPool pool_;
};
svr.new_task_queue = [] {
return new YourThreadPoolTaskQueue(12);
};
```
Client Example
@@ -117,9 +192,12 @@ int main(void)
```c++
std::string body;
auto res = cli.Get("/large-data", [&](const char *data, size_t len) {
body.append(data, len);
});
auto res = cli.Get("/large-data",
[&](const char *data, uint64_t data_length, uint64_t offset, uint64_t content_length) {
body.append(data, data_length);
});
assert(res->body.empty());
```
@@ -226,12 +304,50 @@ auto res = cli.Get("/basic-auth/hello/world", {
httplib::Client cli("httpbin.org");
auto res = cli.Get("/range/32", {
httplib::make_range_header(1, 10) // 'Range: bytes=1-10'
httplib::make_range_header({{1, 10}}) // 'Range: bytes=1-10'
});
// res->status should be 206.
// res->body should be "bcdefghijk".
```
```cpp
httplib::make_range_header({{1, 10}, {20, -1}}) // 'Range: bytes=1-10, 20-'
httplib::make_range_header({{100, 199}, {500, 599}}) // 'Range: bytes=100-199, 500-599'
httplib::make_range_header({{0, 0}, {-1, 1}}) // 'Range: bytes=0-0, -1'
```
### Keep-Alive connection
```cpp
cli.set_keep_alive_max_count(2); // Default is 5
std::vector<Request> requests;
Get(requests, "/get-request1");
Get(requests, "/get-request2");
Post(requests, "/post-request1", "text", "text/plain");
Post(requests, "/post-request2", "text", "text/plain");
std::vector<Response> responses;
if (cli.send(requests, responses)) {
for (const auto& res: responses) {
...
}
}
```
### Redirect
```cpp
httplib::Client cli("yahoo.com");
auto res = cli.Get("/");
res->status; // 301
cli.follow_location(true);
res = cli.Get("/");
res->status; // 200
```
OpenSSL Support
---------------
+10 -2
View File
@@ -15,6 +15,9 @@ using namespace httplib;
int main(void) {
// HTTP server
Server http;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
SSLServer https(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
#endif
http.Get("/test", [](const Request & /*req*/, Response &res) {
res.set_content("Test\n", "text/plain");
@@ -25,8 +28,7 @@ int main(void) {
});
// HTTPS server
SSLServer https(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
https.Get("/", [=](const Request & /*req*/, Response &res) {
res.set_redirect("/hi");
});
@@ -39,18 +41,24 @@ int main(void) {
https.stop();
http.stop();
});
#endif
// Run servers
auto httpThread = std::thread([&]() {
http.listen("localhost", 8080);
});
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto httpsThread = std::thread([&]() {
https.listen("localhost", 8081);
});
#endif
httpThread.join();
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
httpsThread.join();
#endif
return 0;
}
+1121 -294
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -54,6 +54,11 @@
#include <limits>
#include <vector>
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
// Copyright 2005, Google Inc.
// All rights reserved.
//
@@ -19544,4 +19549,8 @@ bool StaticAssertTypeEq() {
} // namespace testing
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
+440 -118
View File
@@ -95,28 +95,100 @@ TEST(GetHeaderValueTest, RegularValueInt) {
TEST(GetHeaderValueTest, Range) {
{
Headers headers = {make_range_header(1)};
Headers headers = {make_range_header({{1, -1}})};
auto val = detail::get_header_value(headers, "Range", 0, 0);
EXPECT_STREQ("bytes=1-", val);
}
{
Headers headers = {make_range_header(1, 10)};
Headers headers = {make_range_header({{-1, 1}})};
auto val = detail::get_header_value(headers, "Range", 0, 0);
EXPECT_STREQ("bytes=-1", val);
}
{
Headers headers = {make_range_header({{1, 10}})};
auto val = detail::get_header_value(headers, "Range", 0, 0);
EXPECT_STREQ("bytes=1-10", val);
}
{
Headers headers = {make_range_header(1, 10, 100)};
Headers headers = {make_range_header({{1, 10}, {100, -1}})};
auto val = detail::get_header_value(headers, "Range", 0, 0);
EXPECT_STREQ("bytes=1-10, 100-", val);
}
{
Headers headers = {make_range_header(1, 10, 100, 200)};
Headers headers = {make_range_header({{1, 10}, {100, 200}})};
auto val = detail::get_header_value(headers, "Range", 0, 0);
EXPECT_STREQ("bytes=1-10, 100-200", val);
}
{
Headers headers = {make_range_header({{0, 0}, {-1, 1}})};
auto val = detail::get_header_value(headers, "Range", 0, 0);
EXPECT_STREQ("bytes=0-0, -1", val);
}
}
TEST(ParseHeaderValueTest, Range) {
{
Ranges ranges;
auto ret = detail::parse_range_header("bytes=1-", ranges);
EXPECT_TRUE(ret);
EXPECT_EQ(1u, ranges.size());
EXPECT_EQ(1u, ranges[0].first);
EXPECT_EQ(-1, ranges[0].second);
}
{
Ranges ranges;
auto ret = detail::parse_range_header("bytes=-1", ranges);
EXPECT_TRUE(ret);
EXPECT_EQ(1u, ranges.size());
EXPECT_EQ(-1, ranges[0].first);
EXPECT_EQ(1u, ranges[0].second);
}
{
Ranges ranges;
auto ret = detail::parse_range_header("bytes=1-10", ranges);
EXPECT_TRUE(ret);
EXPECT_EQ(1u, ranges.size());
EXPECT_EQ(1u, ranges[0].first);
EXPECT_EQ(10u, ranges[0].second);
}
{
Ranges ranges;
auto ret = detail::parse_range_header("bytes=10-1", ranges);
EXPECT_FALSE(ret);
}
{
Ranges ranges;
auto ret = detail::parse_range_header("bytes=1-10, 100-", ranges);
EXPECT_TRUE(ret);
EXPECT_EQ(2u, ranges.size());
EXPECT_EQ(1u, ranges[0].first);
EXPECT_EQ(10u, ranges[0].second);
EXPECT_EQ(100u, ranges[1].first);
EXPECT_EQ(-1, ranges[1].second);
}
{
Ranges ranges;
auto ret =
detail::parse_range_header("bytes=1-10, 100-200, 300-400", ranges);
EXPECT_TRUE(ret);
EXPECT_EQ(3u, ranges.size());
EXPECT_EQ(1u, ranges[0].first);
EXPECT_EQ(10u, ranges[0].second);
EXPECT_EQ(100u, ranges[1].first);
EXPECT_EQ(200u, ranges[1].second);
EXPECT_EQ(300u, ranges[2].first);
EXPECT_EQ(400u, ranges[2].second);
}
}
TEST(ChunkedEncodingTest, FromHTTPWatch) {
@@ -157,7 +229,42 @@ TEST(ChunkedEncodingTest, WithContentReceiver) {
std::string body;
auto res =
cli.Get("/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137",
[&](const char *data, size_t len) { body.append(data, len); });
[&](const char *data, size_t data_length, uint64_t, uint64_t) {
body.append(data, data_length);
return true;
});
ASSERT_TRUE(res != nullptr);
std::string out;
httplib::detail::read_file("./image.jpg", out);
EXPECT_EQ(200, res->status);
EXPECT_EQ(out, body);
}
TEST(ChunkedEncodingTest, WithResponseHandlerAndContentReceiver) {
auto host = "www.httpwatch.com";
auto sec = 2;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443;
httplib::SSLClient cli(host, port, sec);
#else
auto port = 80;
httplib::Client cli(host, port, sec);
#endif
std::string body;
auto res =
cli.Get("/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137", Headers(),
[&](const Response& response) {
EXPECT_EQ(200, response.status);
return true;
},
[&](const char *data, size_t data_length, uint64_t, uint64_t) {
body.append(data, data_length);
return true;
});
ASSERT_TRUE(res != nullptr);
std::string out;
@@ -188,7 +295,7 @@ TEST(RangeTest, FromHTTPBin) {
}
{
httplib::Headers headers = {httplib::make_range_header(1)};
httplib::Headers headers = {httplib::make_range_header({{1, -1}})};
auto res = cli.Get("/range/32", headers);
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(res->body, "bcdefghijklmnopqrstuvwxyzabcdef");
@@ -196,16 +303,39 @@ TEST(RangeTest, FromHTTPBin) {
}
{
httplib::Headers headers = {httplib::make_range_header(1, 10)};
httplib::Headers headers = {httplib::make_range_header({{1, 10}})};
auto res = cli.Get("/range/32", headers);
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(res->body, "bcdefghijk");
EXPECT_EQ(206, res->status);
}
{
httplib::Headers headers = {httplib::make_range_header({{0, 31}})};
auto res = cli.Get("/range/32", headers);
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(res->body, "abcdefghijklmnopqrstuvwxyzabcdef");
EXPECT_EQ(200, res->status);
}
{
httplib::Headers headers = {httplib::make_range_header({{0, -1}})};
auto res = cli.Get("/range/32", headers);
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(res->body, "abcdefghijklmnopqrstuvwxyzabcdef");
EXPECT_EQ(200, res->status);
}
{
httplib::Headers headers = {httplib::make_range_header({{0, 32}})};
auto res = cli.Get("/range/32", headers);
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(416, res->status);
}
}
TEST(ConnectionErrorTest, InvalidHost) {
auto host = "abcde.com";
auto host = "-abcde.com";
auto sec = 2;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
@@ -264,8 +394,7 @@ TEST(CancelTest, NoCancel) {
httplib::Client cli(host, port, sec);
#endif
auto res =
cli.Get("/range/32", [](uint64_t, uint64_t) { return true; });
auto res = cli.Get("/range/32", [](uint64_t, uint64_t) { return true; });
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(res->body, "abcdefghijklmnopqrstuvwxyzabcdef");
EXPECT_EQ(200, res->status);
@@ -283,8 +412,7 @@ TEST(CancelTest, WithCancelSmallPayload) {
httplib::Client cli(host, port, sec);
#endif
auto res =
cli.Get("/range/32", [](uint64_t, uint64_t) { return false; });
auto res = cli.Get("/range/32", [](uint64_t, uint64_t) { return false; });
ASSERT_TRUE(res == nullptr);
}
@@ -325,9 +453,9 @@ TEST(BaseAuthTest, FromHTTPWatch) {
}
{
auto res = cli.Get("/basic-auth/hello/world", {
httplib::make_basic_authentication_header("hello", "world")
});
auto res =
cli.Get("/basic-auth/hello/world",
{httplib::make_basic_authentication_header("hello", "world")});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(res->body,
"{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n");
@@ -335,6 +463,87 @@ TEST(BaseAuthTest, FromHTTPWatch) {
}
}
TEST(AbsoluteRedirectTest, Redirect) {
auto host = "httpbin.org";
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
httplib::SSLClient cli(host);
#else
httplib::Client cli(host);
#endif
cli.follow_location(true);
auto res = cli.Get("/absolute-redirect/3");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(200, res->status);
}
TEST(RedirectTest, Redirect) {
auto host = "httpbin.org";
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
httplib::SSLClient cli(host);
#else
httplib::Client cli(host);
#endif
cli.follow_location(true);
auto res = cli.Get("/redirect/3");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(200, res->status);
}
TEST(RelativeRedirectTest, Redirect) {
auto host = "httpbin.org";
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
httplib::SSLClient cli(host);
#else
httplib::Client cli(host);
#endif
cli.follow_location(true);
auto res = cli.Get("/relative-redirect/3");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(200, res->status);
}
TEST(TooManyRedirectTest, Redirect) {
auto host = "httpbin.org";
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
httplib::SSLClient cli(host);
#else
httplib::Client cli(host);
#endif
cli.follow_location(true);
auto res = cli.Get("/redirect/21");
ASSERT_TRUE(res == nullptr);
}
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
TEST(YahooRedirectTest, Redirect) {
httplib::Client cli("yahoo.com");
auto res = cli.Get("/");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(301, res->status);
cli.follow_location(true);
res = cli.Get("/");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(200, res->status);
}
TEST(HttpsToHttpRedirectTest, Redirect) {
httplib::SSLClient cli("httpbin.org");
cli.follow_location(true);
auto res = cli.Get("/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
ASSERT_TRUE(res != nullptr);
}
#endif
TEST(Server, BindAndListenSeparately) {
Server svr;
int port = svr.bind_to_any_port("localhost");
@@ -402,28 +611,54 @@ protected:
res.set_content(json, "appliation/json");
res.status = 200;
})
.Get("/streamedchunked",
.Get("/streamed-chunked",
[&](const Request & /*req*/, Response &res) {
res.content_producer = [](uint64_t offset) {
if (offset < 3) return "a";
if (offset < 6) return "b";
return "";
};
res.set_chunked_content_provider(
[](uint64_t /*offset*/, DataSink sink, Done done) {
sink("123", 3);
sink("456", 3);
sink("789", 3);
done();
});
})
.Get("/streamed",
[&](const Request & /*req*/, Response &res) {
res.set_header("Content-Length", "6");
res.content_producer = [](uint64_t offset) {
if (offset < 3) return "a";
if (offset < 6) return "b";
return "";
};
res.set_content_provider(
6, [](uint64_t offset, uint64_t /*length*/, DataSink sink) {
sink(offset < 3 ? "a" : "b", 1);
});
})
.Get("/streamed-with-range",
[&](const Request & /*req*/, Response &res) {
auto data = new std::string("abcdefg");
res.set_content_provider(
data->size(),
[data](uint64_t offset, uint64_t length, DataSink sink) {
size_t DATA_CHUNK_SIZE = 4;
const auto &d = *data;
auto out_len = std::min(static_cast<size_t>(length), DATA_CHUNK_SIZE);
sink(&d[static_cast<size_t>(offset)], out_len);
},
[data] { delete data; });
})
.Get("/streamed-cancel",
[&](const Request & /*req*/, Response &res) {
res.set_content_provider(
size_t(-1),
[](uint64_t /*offset*/, uint64_t /*length*/, DataSink sink) {
std::string data = "data_chunk";
sink(data.data(), data.size());
});
})
.Get("/with-range",
[&](const Request & /*req*/, Response &res) {
res.set_content("abcdefg", "text/plain");
})
.Post("/chunked",
[&](const Request &req, Response & /*res*/) {
EXPECT_EQ(req.body, "dechunked post body");
})
.Post("/largechunked",
.Post("/large-chunked",
[&](const Request &req, Response & /*res*/) {
std::string expected(6 * 30 * 1024u, 'a');
EXPECT_EQ(req.body, expected);
@@ -579,7 +814,6 @@ TEST_F(ServerTest, GetMethod200) {
EXPECT_EQ(200, res->status);
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
EXPECT_EQ(1, res->get_header_value_count("Content-Type"));
EXPECT_EQ("close", res->get_header_value("Connection"));
EXPECT_EQ("Hello World!", res->body);
}
@@ -737,85 +971,29 @@ TEST_F(ServerTest, EmptyRequest) {
}
TEST_F(ServerTest, LongRequest) {
auto res =
cli_.Get("/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/__ok__");
std::string request;
for (size_t i = 0; i < 545; i++) {
request += "/TooLongRequest";
}
request += "OK";
auto res = cli_.Get(request.c_str());
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(404, res->status);
}
TEST_F(ServerTest, TooLongRequest) {
auto res =
cli_.Get("/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/"
"TooLongRequest/TooLongRequest/TooLongRequest/__ng___");
std::string request;
for (size_t i = 0; i < 545; i++) {
request += "/TooLongRequest";
}
request += "_NG";
auto res = cli_.Get(request.c_str());
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(404, res->status);
EXPECT_EQ(414, res->status);
}
TEST_F(ServerTest, LongHeader) {
@@ -963,11 +1141,11 @@ TEST_F(ServerTest, EndWithPercentCharacterInQuery) {
TEST_F(ServerTest, MultipartFormData) {
MultipartFormDataItems items = {
{ "text1", "text default", "", "" },
{ "text2", "aωb", "", "" },
{ "file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain" },
{ "file2", "{\n \"world\", true\n}\n", "world.json", "application/json" },
{ "file3", "", "", "application/octet-stream" },
{"text1", "text default", "", ""},
{"text2", "aωb", "", ""},
{"file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain"},
{"file2", "{\n \"world\", true\n}\n", "world.json", "application/json"},
{"file3", "", "", "application/octet-stream"},
};
auto res = cli_.Post("/multipart", items);
@@ -1013,25 +1191,114 @@ TEST_F(ServerTest, CaseInsensitiveTransferEncoding) {
EXPECT_EQ(200, res->status);
}
TEST_F(ServerTest, GetStreamed2) {
auto res = cli_.Get("/streamed", {{make_range_header({{2, 3}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("2", res->get_header_value("Content-Length"));
EXPECT_EQ(std::string("ab"), res->body);
}
TEST_F(ServerTest, GetStreamed) {
auto res = cli_.Get("/streamed");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(200, res->status);
EXPECT_EQ("6", res->get_header_value("Content-Length"));
EXPECT_TRUE(res->body == "aaabbb");
EXPECT_EQ(std::string("aaabbb"), res->body);
}
TEST_F(ServerTest, GetStreamedWithRange1) {
auto res = cli_.Get("/streamed-with-range", {{make_range_header({{3, 5}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("3", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("def"), res->body);
}
TEST_F(ServerTest, GetStreamedWithRange2) {
auto res = cli_.Get("/streamed-with-range", {{make_range_header({{1, -1}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("6", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("bcdefg"), res->body);
}
TEST_F(ServerTest, GetStreamedWithRangeMultipart) {
auto res =
cli_.Get("/streamed-with-range", {{make_range_header({{1, 2}, {4, 5}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("269", res->get_header_value("Content-Length"));
EXPECT_EQ(false, res->has_header("Content-Range"));
EXPECT_EQ(269, res->body.size());
}
TEST_F(ServerTest, GetStreamedEndless) {
auto res = cli_.Get("/streamed-cancel",
[](const char * /*data*/, uint64_t /*data_length*/,
uint64_t offset,
uint64_t /*content_length*/) { return offset < 100; });
ASSERT_TRUE(res == nullptr);
}
TEST_F(ServerTest, GetWithRange1) {
auto res = cli_.Get("/with-range", {{make_range_header({{3, 5}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("3", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("def"), res->body);
}
TEST_F(ServerTest, GetWithRange2) {
auto res = cli_.Get("/with-range", {{make_range_header({{1, -1}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("6", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("bcdefg"), res->body);
}
TEST_F(ServerTest, GetWithRange3) {
auto res = cli_.Get("/with-range", {{make_range_header({{0, 0}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("1", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("a"), res->body);
}
TEST_F(ServerTest, GetWithRange4) {
auto res = cli_.Get("/with-range", {{make_range_header({{-1, 2}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("2", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("fg"), res->body);
}
TEST_F(ServerTest, GetWithRangeMultipart) {
auto res = cli_.Get("/with-range", {{make_range_header({{1, 2}, {4, 5}})}});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status);
EXPECT_EQ("269", res->get_header_value("Content-Length"));
EXPECT_EQ(false, res->has_header("Content-Range"));
EXPECT_EQ(269, res->body.size());
}
TEST_F(ServerTest, GetStreamedChunked) {
auto res = cli_.Get("/streamedchunked");
auto res = cli_.Get("/streamed-chunked");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(200, res->status);
EXPECT_TRUE(res->body == "aaabbb");
EXPECT_EQ(std::string("123456789"), res->body);
}
TEST_F(ServerTest, LargeChunkedPost) {
Request req;
req.method = "POST";
req.path = "/largechunked";
req.path = "/large-chunked";
std::string host_and_port;
host_and_port += HOST;
@@ -1119,15 +1386,61 @@ TEST_F(ServerTest, ArrayParam) {
}
TEST_F(ServerTest, NoMultipleHeaders) {
Headers headers = {
{ "Content-Length", "5" }
};
Headers headers = {{"Content-Length", "5"}};
auto res = cli_.Post("/validate-no-multiple-headers", headers, "hello",
"text/plain");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(200, res->status);
}
TEST_F(ServerTest, HTTP2Magic) {
Request req;
req.method = "PRI";
req.path = "*";
req.body = "SM";
auto res = std::make_shared<Response>();
auto ret = cli_.send(req, *res);
ASSERT_TRUE(ret);
EXPECT_EQ(400, res->status);
}
TEST_F(ServerTest, KeepAlive) {
cli_.set_keep_alive_max_count(4);
std::vector<Request> requests;
Get(requests, "/hi");
Get(requests, "/hi");
Get(requests, "/hi");
Get(requests, "/not-exist");
Post(requests, "/empty", "", "text/plain");
std::vector<Response> responses;
auto ret = cli_.send(requests, responses);
ASSERT_TRUE(ret == true);
ASSERT_TRUE(requests.size() == responses.size());
for (int i = 0; i < 3; i++) {
auto& res = responses[i];
EXPECT_EQ(200, res.status);
EXPECT_EQ("text/plain", res.get_header_value("Content-Type"));
EXPECT_EQ("Hello World!", res.body);
}
{
auto& res = responses[3];
EXPECT_EQ(404, res.status);
}
{
auto& res = responses[4];
EXPECT_EQ(200, res.status);
EXPECT_EQ("text/plain", res.get_header_value("Content-Type"));
EXPECT_EQ("empty", res.body);
}
}
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
TEST_F(ServerTest, Gzip) {
Headers headers;
@@ -1148,9 +1461,12 @@ TEST_F(ServerTest, GzipWithContentReceiver) {
Headers headers;
headers.emplace("Accept-Encoding", "gzip, deflate");
std::string body;
auto res = cli_.Get("/gzip", headers, [&](const char *data, size_t len) {
body.append(data, len);
});
auto res = cli_.Get("/gzip", headers,
[&](const char *data, uint64_t data_length,
uint64_t /*offset*/, uint64_t /*content_length*/) {
body.append(data, data_length);
return true;
});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ("gzip", res->get_header_value("Content-Encoding"));
@@ -1181,9 +1497,12 @@ TEST_F(ServerTest, NoGzipWithContentReceiver) {
Headers headers;
headers.emplace("Accept-Encoding", "gzip, deflate");
std::string body;
auto res = cli_.Get("/nogzip", headers, [&](const char *data, size_t len) {
body.append(data, len);
});
auto res = cli_.Get("/nogzip", headers,
[&](const char *data, uint64_t data_length,
uint64_t /*offset*/, uint64_t /*content_length*/) {
body.append(data, data_length);
return true;
});
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(false, res->has_header("Content-Encoding"));
@@ -1443,6 +1762,7 @@ TEST(SSLClientServerTest, ClientCertPresent) {
});
thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
msleep(1);
httplib::SSLClient cli(HOST, PORT, 30, CLIENT_CERT_FILE,
CLIENT_PRIVATE_KEY_FILE);
@@ -1461,6 +1781,7 @@ TEST(SSLClientServerTest, ClientCertMissing) {
svr.Get("/test", [&](const Request &, Response &) { ASSERT_TRUE(false); });
thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
msleep(1);
httplib::SSLClient cli(HOST, PORT, 30);
auto res = cli.Get("/test");
@@ -1481,6 +1802,7 @@ TEST(SSLClientServerTest, TrustDirOptional) {
});
thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
msleep(1);
httplib::SSLClient cli(HOST, PORT, 30, CLIENT_CERT_FILE,
CLIENT_PRIVATE_KEY_FILE);
+20 -4
View File
@@ -34,7 +34,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
@@ -47,7 +47,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
@@ -69,15 +69,23 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>C:\Program Files\OpenSSL-Win64\lib\VC;C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files\OpenSSL-Win64\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>C:\Program Files\OpenSSL-Win64\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files\OpenSSL-Win64\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -87,6 +95,8 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
<AdditionalUsingDirectories>
</AdditionalUsingDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -102,11 +112,13 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
<AdditionalUsingDirectories>
</AdditionalUsingDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Ws2_32.lib;libssl.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -119,6 +131,8 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
<AdditionalUsingDirectories>
</AdditionalUsingDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -138,13 +152,15 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;../</AdditionalIncludeDirectories>
<AdditionalUsingDirectories>
</AdditionalUsingDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Ws2_32.lib;libssl.lib;libcrypto.lib;libssl.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>