Compare commits

...

24 Commits

Author SHA1 Message Date
yhirose 68d1281759 Resolve #839 2021-01-23 13:33:27 -05:00
yhirose 0308d60cb2 Resolve #831 (#835) 2021-01-23 12:23:06 -05:00
yhirose 59f5fdbb33 Resolve #840 2021-01-23 11:43:01 -05:00
Anonymous 13184f5f80 Return Server& from handler setters (#836)
* Update httplib.h

* Update httplib.h

* Update httplib.h

* Update httplib.h
2021-01-22 09:20:21 -05:00
Eric Lee 8d9a477edb No content check (#823)
* No content check

* unit test for no content

* fixing merge conflict break

* oops during manual merge conflict
2021-01-13 17:51:40 -05:00
yhirose 85b4abbf16 Updated the simple example 2021-01-07 19:56:33 -05:00
yhirose e42a358da8 Updated README 2021-01-07 19:00:24 -05:00
yhirose f008fe4539 Added middleware support (#816) 2021-01-07 18:40:52 -05:00
yhirose ddf41d29ef Added const *char and size_t interface 2021-01-06 22:39:58 -05:00
yhirose 3f88a46c4a Code format 2020-12-31 18:14:28 -05:00
yhirose 242706ea34 Fix #820 2020-12-31 18:14:05 -05:00
yhirose a9f5f8683f Fixed warnings on Visual C++ 2020-12-31 11:35:11 -05:00
yhirose 60c2213893 Fix #817 2020-12-31 10:58:44 -05:00
yhirose eb2d28bca2 Code cleanup 2020-12-31 10:37:06 -05:00
Yuri Santos 86f637a246 Added encode_uri_param tests with UTF-8 characters (#818)
Remove additional lines between tests
2020-12-30 23:06:36 -05:00
yhirose 2c07ec4600 Code cleanup 2020-12-29 09:39:19 -05:00
yhirose 871d8d67b0 Made Request paramater const in handle_file_request 2020-12-28 22:03:44 -05:00
Anonymous 7299713195 Fix readme Response::set_chunked_content_provider (#811)
`Response::set_chunked_content_provider` has formal parameters, not one.
2020-12-25 19:55:57 -05:00
yhirose 96afa7e108 Updated README 2020-12-21 13:40:32 -05:00
yhirose 55f57af0b9 Update README 2020-12-21 09:27:36 -05:00
yhirose 6b35cd0116 Updated README 2020-12-21 08:15:06 -05:00
yhirose 99f2229e48 Updated README 2020-12-19 22:43:31 -05:00
yhirose b9641048fc Switch to hghttp2.org/httpbin for redirect test. (#538) 2020-12-19 20:27:52 -05:00
yhirose e9c6c6e609 Code format 2020-12-19 20:14:53 -05:00
4 changed files with 912 additions and 298 deletions
+86 -68
View File
@@ -15,8 +15,15 @@ Simple examples
#### Server
```c++
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include "path/to/httplib.h"
// HTTP
httplib::Server svr;
// HTTPS
httplib::SSLServer svr;
svr.Get("/hi", [](const httplib::Request &, httplib::Response &res) {
res.set_content("Hello World!", "text/plain");
});
@@ -27,12 +34,18 @@ svr.listen("0.0.0.0", 8080);
#### Client
```c++
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include "path/to/httplib.h"
// HTTP
httplib::Client cli("http://cpp-httplib-server.yhirose.repl.co");
auto res = cli.Get("/hi");
// HTTPS
httplib::Client cli("https://cpp-httplib-server.yhirose.repl.co");
res->status; // 200
res->body; // "Hello World!"
auto res = cli.Get("/hi");
res->status;
res->body;
```
### Try out the examples on Repl.it!
@@ -120,48 +133,28 @@ svr.set_file_extension_and_mimetype_mapping("hh", "text/x-h");
The followings are built-in mappings:
| Extension | MIME Type |
| :--------- | :-------------------------- |
| css | text/css |
| csv | text/csv |
| txt | text/plain |
| vtt | text/vtt |
| html, htm | text/html |
| apng | image/apng |
| avif | image/avif |
| bmp | image/bmp |
| gif | image/gif |
| png | image/png |
| svg | image/svg+xml |
| webp | image/webp |
| ico | image/x-icon |
| tif | image/tiff |
| tiff | image/tiff |
| jpeg, jpg | image/jpeg |
| mp4 | video/mp4 |
| mpeg | video/mpeg |
| webm | video/webm |
| mp3 | audio/mp3 |
| mpga | audio/mpeg |
| weba | audio/webm |
| wav | audio/wave |
| otf | font/otf |
| ttf | font/ttf |
| woff | font/woff |
| woff2 | font/woff2 |
| 7z | application/x-7z-compressed |
| atom | application/atom+xml |
| pdf | application/pdf |
| mjs, js | application/javascript |
| json | application/json |
| rss | application/rss+xml |
| tar | application/x-tar |
| xhtml, xht | application/xhtml+xml |
| xslt | application/xslt+xml |
| xml | application/xml |
| gz | application/gzip |
| zip | application/zip |
| wasm | application/wasm |
| Extension | MIME Type | Extension | MIME Type |
| :--------- | :-------------------------- | :--------- | :-------------------------- |
| css | text/css | mpga | audio/mpeg |
| csv | text/csv | weba | audio/webm |
| txt | text/plain | wav | audio/wave |
| vtt | text/vtt | otf | font/otf |
| html, htm | text/html | ttf | font/ttf |
| apng | image/apng | woff | font/woff |
| avif | image/avif | woff2 | font/woff2 |
| bmp | image/bmp | 7z | application/x-7z-compressed |
| gif | image/gif | atom | application/atom+xml |
| png | image/png | pdf | application/pdf |
| svg | image/svg+xml | mjs, js | application/javascript |
| webp | image/webp | json | application/json |
| ico | image/x-icon | rss | application/rss+xml |
| tif | image/tiff | tar | application/x-tar |
| tiff | image/tiff | xhtml, xht | application/xhtml+xml |
| jpeg, jpg | image/jpeg | xslt | application/xslt+xml |
| mp4 | video/mp4 | xml | application/xml |
| mpeg | video/mpeg | gz | application/gzip |
| webm | video/webm | zip | application/zip |
| mp3 | audio/mp3 | wasm | application/wasm |
NOTE: These static file server methods are not thread-safe.
@@ -184,6 +177,26 @@ svr.set_error_handler([](const auto& req, auto& res) {
});
```
### Pre routing handler
```cpp
svr.set_pre_routing_handler([](const auto& req, auto& res) -> bool {
if (req.path == "/hello") {
res.set_content("world", "text/html");
return true; // This request is handled
}
return false; // Let the router handle this request
});
```
### Post routing handler
```cpp
svr.set_post_routing_handler([](const auto& req, auto& res) {
res.set_header("ADDITIONAL_HEADER", "value");
});
```
### 'multipart/form-data' POST data
```cpp
@@ -268,6 +281,7 @@ svr.Get("/stream", [&](const Request &req, Response &res) {
```cpp
svr.Get("/chunked", [&](const Request& req, Response& res) {
res.set_chunked_content_provider(
"text/plain",
[](size_t offset, DataSink &sink) {
sink.write("123", 3);
sink.write("345", 3);
@@ -390,6 +404,7 @@ httplib::Client cli("localhost:8080");
httplib::Client cli("http://localhost");
httplib::Client cli("http://localhost:8080");
httplib::Client cli("https://localhost");
httplib::SSLClient cli("localhost");
```
### Error code
@@ -655,29 +670,6 @@ NOTE: This feature is not available on Windows, yet.
cli.set_interface("eth0"); // Interface name, IP address or host name
```
OpenSSL Support
---------------
SSL support is available with `CPPHTTPLIB_OPENSSL_SUPPORT`. `libssl` and `libcrypto` should be linked.
NOTE: cpp-httplib currently supports only version 1.1.1.
```c++
#define CPPHTTPLIB_OPENSSL_SUPPORT
httplib::SSLServer svr("./cert.pem", "./key.pem");
httplib::SSLClient cli("localhost", 1234); // or `httplib::Client cli("https://localhost:1234");`
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
-----------
@@ -714,6 +706,32 @@ res = cli.Get("/resource/foo", {{"Accept-Encoding", "gzip, deflate, br"}});
res->body; // Compressed data
```
SSL Support
-----------
SSL support is available with `CPPHTTPLIB_OPENSSL_SUPPORT`. `libssl` and `libcrypto` should be linked.
NOTE: cpp-httplib currently supports only version 1.1.1.
```c++
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include "path/to/httplib.h"
// Server
httplib::SSLServer svr("./cert.pem", "./key.pem");
// Client
httplib::Client cli("https://localhost:1234");
// Use your CA bundle
cli.set_ca_cert_path("./ca-bundle.crt");
// Disable cert verification
cli.enable_server_certificate_verification(false);
```
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.
Split httplib.h into .h and .cc
-------------------------------
+501 -174
View File
File diff suppressed because it is too large Load Diff
+298 -26
View File
@@ -46,16 +46,31 @@ TEST(StartupTest, WSAStartup) {
}
#endif
TEST(EncodeQueryParamTest, ParseUnescapedChararactersTest){
TEST(EncodeQueryParamTest, ParseUnescapedChararactersTest) {
string unescapedCharacters = "-_.!~*'()";
EXPECT_EQ(detail::encode_query_param(unescapedCharacters), "-_.!~*'()");
}
TEST(EncodeQueryParamTest, ParseReservedCharactersTest){
TEST(EncodeQueryParamTest, ParseReservedCharactersTest) {
string reservedCharacters = ";,/?:@&=+$";
EXPECT_EQ(detail::encode_query_param(reservedCharacters), "%3B%2C%2F%3F%3A%40%26%3D%2B%24");
EXPECT_EQ(detail::encode_query_param(reservedCharacters),
"%3B%2C%2F%3F%3A%40%26%3D%2B%24");
}
TEST(EncodeQueryParamTest, TestUTF8Characters) {
string chineseCharacters = "中国語";
string russianCharacters = "дом";
string brazilianCharacters = "óculos";
EXPECT_EQ(detail::encode_query_param(chineseCharacters),
"%E4%B8%AD%E5%9B%BD%E8%AA%9E");
EXPECT_EQ(detail::encode_query_param(russianCharacters),
"%D0%B4%D0%BE%D0%BC");
EXPECT_EQ(detail::encode_query_param(brazilianCharacters), "%C3%B3culos");
}
TEST(TrimTests, TrimStringTests) {
@@ -717,9 +732,8 @@ TEST(DigestAuthTest, FromHTTPWatch) {
}
#endif
#if 0
TEST(AbsoluteRedirectTest, Redirect) {
auto host = "httpbin.org";
auto host = "nghttp2.org";
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
SSLClient cli(host);
@@ -728,13 +742,13 @@ TEST(AbsoluteRedirectTest, Redirect) {
#endif
cli.set_follow_location(true);
auto res = cli.Get("/absolute-redirect/3");
auto res = cli.Get("/httpbin/absolute-redirect/3");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
TEST(RedirectTest, Redirect) {
auto host = "httpbin.org";
auto host = "nghttp2.org";
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
SSLClient cli(host);
@@ -743,13 +757,13 @@ TEST(RedirectTest, Redirect) {
#endif
cli.set_follow_location(true);
auto res = cli.Get("/redirect/3");
auto res = cli.Get("/httpbin/redirect/3");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
TEST(RelativeRedirectTest, Redirect) {
auto host = "httpbin.org";
auto host = "nghttp2.org";
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
SSLClient cli(host);
@@ -758,13 +772,13 @@ TEST(RelativeRedirectTest, Redirect) {
#endif
cli.set_follow_location(true);
auto res = cli.Get("/relative-redirect/3");
auto res = cli.Get("/httpbin/relative-redirect/3");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
TEST(TooManyRedirectTest, Redirect) {
auto host = "httpbin.org";
auto host = "nghttp2.org";
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
SSLClient cli(host);
@@ -773,11 +787,10 @@ TEST(TooManyRedirectTest, Redirect) {
#endif
cli.set_follow_location(true);
auto res = cli.Get("/redirect/21");
auto res = cli.Get("/httpbin/redirect/21");
ASSERT_TRUE(!res);
EXPECT_EQ(Error::ExceedRedirectCount, res.error());
}
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
TEST(YahooRedirectTest, Redirect) {
@@ -794,16 +807,39 @@ TEST(YahooRedirectTest, Redirect) {
EXPECT_EQ("https://yahoo.com/", res->location);
}
#if 0
TEST(HttpsToHttpRedirectTest, Redirect) {
SSLClient cli("httpbin.org");
SSLClient cli("nghttp2.org");
cli.set_follow_location(true);
auto res =
cli.Get("/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
auto res = cli.Get(
"/httpbin/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
TEST(HttpsToHttpRedirectTest2, Redirect) {
SSLClient cli("nghttp2.org");
cli.set_follow_location(true);
Params params;
params.emplace("url", "http://www.google.com");
params.emplace("status_code", "302");
auto res = cli.Get("/httpbin/redirect-to", params, Headers{});
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
TEST(HttpsToHttpRedirectTest3, Redirect) {
SSLClient cli("nghttp2.org");
cli.set_follow_location(true);
Params params;
params.emplace("url", "http://www.google.com");
auto res = cli.Get("/httpbin/redirect-to?status_code=302", params, Headers{});
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
#endif
TEST(RedirectToDifferentPort, Redirect) {
Server svr8080;
@@ -942,6 +978,101 @@ TEST(ErrorHandlerTest, ContentLength) {
ASSERT_FALSE(svr.is_running());
}
TEST(NoContentTest, ContentLength) {
Server svr;
svr.Get("/hi",
[](const Request & /*req*/, Response &res) { res.status = 204; });
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(204, res->status);
EXPECT_EQ("0", res->get_header_value("Content-Length"));
}
svr.stop();
thread.join();
ASSERT_FALSE(svr.is_running());
}
TEST(RoutingHandlerTest, PreRoutingHandler) {
Server svr;
svr.set_pre_routing_handler([](const Request &req, Response &res) {
if (req.path == "/routing_handler") {
res.set_header("PRE_ROUTING", "on");
res.set_content("Routing Handler", "text/plain");
return httplib::Server::HandlerResponse::Handled;
}
return httplib::Server::HandlerResponse::Unhandled;
});
svr.set_error_handler([](const Request & /*req*/, Response &res) {
res.set_content("Error", "text/html");
});
svr.set_post_routing_handler([](const Request &req, Response &res) {
if (req.path == "/routing_handler") {
res.set_header("POST_ROUTING", "on");
}
});
svr.Get("/hi", [](const Request & /*req*/, Response &res) {
res.set_content("Hello World!\n", "text/plain");
});
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("/routing_handler");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("Routing Handler", res->body);
EXPECT_EQ(1, res->get_header_value_count("PRE_ROUTING"));
EXPECT_EQ("on", res->get_header_value("PRE_ROUTING"));
EXPECT_EQ(1, res->get_header_value_count("POST_ROUTING"));
EXPECT_EQ("on", res->get_header_value("POST_ROUTING"));
}
{
Client cli(HOST, PORT);
auto res = cli.Get("/hi");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("Hello World!\n", res->body);
EXPECT_EQ(0, res->get_header_value_count("PRE_ROUTING"));
EXPECT_EQ(0, res->get_header_value_count("POST_ROUTING"));
}
{
Client cli(HOST, PORT);
auto res = cli.Get("/aaa");
ASSERT_TRUE(res);
EXPECT_EQ(404, res->status);
EXPECT_EQ("Error", res->body);
EXPECT_EQ(0, res->get_header_value_count("PRE_ROUTING"));
EXPECT_EQ(0, res->get_header_value_count("POST_ROUTING"));
}
svr.stop();
thread.join();
ASSERT_FALSE(svr.is_running());
}
TEST(InvalidFormatTest, StatusCode) {
Server svr;
@@ -1373,6 +1504,38 @@ protected:
std::string url = "/redirect/" + std::to_string(num);
res.set_redirect(url);
})
.Post("/binary",
[&](const Request &req, Response &res) {
EXPECT_EQ(4, req.body.size());
EXPECT_EQ("application/octet-stream",
req.get_header_value("Content-Type"));
EXPECT_EQ("4", req.get_header_value("Content-Length"));
res.set_content(req.body, "application/octet-stream");
})
.Put("/binary",
[&](const Request &req, Response &res) {
EXPECT_EQ(4, req.body.size());
EXPECT_EQ("application/octet-stream",
req.get_header_value("Content-Type"));
EXPECT_EQ("4", req.get_header_value("Content-Length"));
res.set_content(req.body, "application/octet-stream");
})
.Patch("/binary",
[&](const Request &req, Response &res) {
EXPECT_EQ(4, req.body.size());
EXPECT_EQ("application/octet-stream",
req.get_header_value("Content-Type"));
EXPECT_EQ("4", req.get_header_value("Content-Length"));
res.set_content(req.body, "application/octet-stream");
})
.Delete("/binary",
[&](const Request &req, Response &res) {
EXPECT_EQ(4, req.body.size());
EXPECT_EQ("application/octet-stream",
req.get_header_value("Content-Type"));
EXPECT_EQ("4", req.get_header_value("Content-Length"));
res.set_content(req.body, "application/octet-stream");
})
#if defined(CPPHTTPLIB_ZLIB_SUPPORT) || defined(CPPHTTPLIB_BROTLI_SUPPORT)
.Get("/compress",
[&](const Request & /*req*/, Response &res) {
@@ -1727,6 +1890,58 @@ TEST_F(ServerTest, InvalidBaseDirMount) {
EXPECT_EQ(false, svr_.set_mount_point("invalid_mount_point", "./www3"));
}
TEST_F(ServerTest, Binary) {
std::vector<char> binary{0x00, 0x01, 0x02, 0x03};
auto res = cli_.Post("/binary", binary.data(), binary.size(),
"application/octet-stream");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
ASSERT_EQ(4, res->body.size());
res = cli_.Put("/binary", binary.data(), binary.size(),
"application/octet-stream");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
ASSERT_EQ(4, res->body.size());
res = cli_.Patch("/binary", binary.data(), binary.size(),
"application/octet-stream");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
ASSERT_EQ(4, res->body.size());
res = cli_.Delete("/binary", binary.data(), binary.size(),
"application/octet-stream");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
ASSERT_EQ(4, res->body.size());
}
TEST_F(ServerTest, BinaryString) {
auto binary = std::string("\x00\x01\x02\x03", 4);
auto res = cli_.Post("/binary", binary, "application/octet-stream");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
ASSERT_EQ(4, res->body.size());
res = cli_.Put("/binary", binary, "application/octet-stream");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
ASSERT_EQ(4, res->body.size());
res = cli_.Patch("/binary", binary, "application/octet-stream");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
ASSERT_EQ(4, res->body.size());
res = cli_.Delete("/binary", binary, "application/octet-stream");
ASSERT_TRUE(res);
ASSERT_EQ(200, res->status);
ASSERT_EQ(4, res->body.size());
}
TEST_F(ServerTest, EmptyRequest) {
auto res = cli_.Get("");
ASSERT_TRUE(!res);
@@ -3136,9 +3351,9 @@ TEST(MountTest, Unmount) {
TEST(ExceptionTest, ThrowExceptionInHandler) {
Server svr;
svr.Get("/hi", [&](const Request & /*req*/, Response &res) {
svr.Get("/hi", [&](const Request & /*req*/, Response & /*res*/) {
throw std::runtime_error("exception...");
res.set_content("Hello World!", "text/plain");
// res.set_content("Hello World!", "text/plain");
});
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
@@ -3199,6 +3414,39 @@ TEST(KeepAliveTest, ReadTimeout) {
ASSERT_FALSE(svr.is_running());
}
TEST(ErrorHandlerWithContentProviderTest, ErrorHandler) {
Server svr;
svr.set_error_handler([](Request const &, Response &res) -> void {
res.set_chunked_content_provider(
"text/plain", [](std::size_t const, DataSink &sink) -> bool {
sink.os << "hello";
sink.os << "world";
sink.done();
return true;
});
});
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
while (!svr.is_running()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli("localhost", PORT);
auto res = cli.Get("/");
ASSERT_TRUE(res);
EXPECT_EQ(404, res->status);
EXPECT_EQ("helloworld", res->body);
svr.stop();
listen_thread.join();
ASSERT_FALSE(svr.is_running());
}
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
TEST(KeepAliveTest, ReadTimeoutSSL) {
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
@@ -3755,15 +4003,39 @@ TEST(DecodeWithChunkedEncoding, BrotliEncoding) {
}
#endif
#if 0
TEST(HttpsToHttpRedirectTest2, SimpleInterface) {
TEST(HttpsToHttpRedirectTest, SimpleInterface) {
Client cli("https://nghttp2.org");
cli.set_follow_location(true);
auto res =
Client("https://httpbin.org")
.set_follow_location(true)
.Get("/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
cli.Get("/httpbin/"
"redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
#endif
TEST(HttpsToHttpRedirectTest2, SimpleInterface) {
Client cli("https://nghttp2.org");
cli.set_follow_location(true);
Params params;
params.emplace("url", "http://www.google.com");
params.emplace("status_code", "302");
auto res = cli.Get("/httpbin/redirect-to", params, Headers{});
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
TEST(HttpsToHttpRedirectTest3, SimpleInterface) {
Client cli("https://nghttp2.org");
cli.set_follow_location(true);
Params params;
params.emplace("url", "http://www.google.com");
auto res = cli.Get("/httpbin/redirect-to?status_code=302", params, Headers{});
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
}
#endif
+27 -30
View File
@@ -8,29 +8,29 @@ using namespace httplib;
template <typename T>
void ProxyTest(T& cli, bool basic) {
cli.set_proxy("localhost", basic ? 3128 : 3129);
auto res = cli.Get("/get");
auto res = cli.Get("/httpbin/get");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(407, res->status);
}
TEST(ProxyTest, NoSSLBasic) {
Client cli("httpbin.org");
Client cli("nghttp2.org");
ProxyTest(cli, true);
}
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
TEST(ProxyTest, SSLBasic) {
SSLClient cli("httpbin.org");
SSLClient cli("nghttp2.org");
ProxyTest(cli, true);
}
TEST(ProxyTest, NoSSLDigest) {
Client cli("httpbin.org");
Client cli("nghttp2.org");
ProxyTest(cli, false);
}
TEST(ProxyTest, SSLDigest) {
SSLClient cli("httpbin.org");
SSLClient cli("nghttp2.org");
ProxyTest(cli, false);
}
#endif
@@ -54,29 +54,27 @@ void RedirectProxyText(T& cli, const char *path, bool basic) {
EXPECT_EQ(200, res->status);
}
#if 0
TEST(RedirectTest, HTTPBinNoSSLBasic) {
Client cli("httpbin.org");
RedirectProxyText(cli, "/redirect/2", true);
Client cli("nghttp2.org");
RedirectProxyText(cli, "/httpbin/redirect/2", true);
}
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
TEST(RedirectTest, HTTPBinNoSSLDigest) {
Client cli("httpbin.org");
RedirectProxyText(cli, "/redirect/2", false);
Client cli("nghttp2.org");
RedirectProxyText(cli, "/httpbin/redirect/2", false);
}
TEST(RedirectTest, HTTPBinSSLBasic) {
SSLClient cli("httpbin.org");
RedirectProxyText(cli, "/redirect/2", true);
SSLClient cli("nghttp2.org");
RedirectProxyText(cli, "/httpbin/redirect/2", true);
}
TEST(RedirectTest, HTTPBinSSLDigest) {
SSLClient cli("httpbin.org");
RedirectProxyText(cli, "/redirect/2", false);
SSLClient cli("nghttp2.org");
RedirectProxyText(cli, "/httpbin/redirect/2", false);
}
#endif
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
TEST(RedirectTest, YouTubeNoSSLBasic) {
@@ -218,7 +216,8 @@ TEST(DigestAuthTest, NoSSL) {
// ----------------------------------------------------------------------------
void KeepAliveTest(Client& cli, bool basic) {
template <typename T>
void KeepAliveTest(T& cli, bool basic) {
cli.set_proxy("localhost", basic ? 3128 : 3129);
if (basic) {
cli.set_proxy_basic_auth("hello", "world");
@@ -234,20 +233,20 @@ void KeepAliveTest(Client& cli, bool basic) {
#endif
{
auto res = cli.Get("/get");
auto res = cli.Get("/httpbin/get");
EXPECT_EQ(200, res->status);
}
{
auto res = cli.Get("/redirect/2");
auto res = cli.Get("/httpbin/redirect/2");
EXPECT_EQ(200, res->status);
}
{
std::vector<std::string> paths = {
"/digest-auth/auth/hello/world/MD5",
"/digest-auth/auth/hello/world/SHA-256",
"/digest-auth/auth/hello/world/SHA-512",
"/digest-auth/auth-int/hello/world/MD5",
"/httpbin/digest-auth/auth/hello/world/MD5",
"/httpbin/digest-auth/auth/hello/world/SHA-256",
"/httpbin/digest-auth/auth/hello/world/SHA-512",
"/httpbin/digest-auth/auth-int/hello/world/MD5",
};
for (auto path: paths) {
@@ -258,34 +257,32 @@ void KeepAliveTest(Client& cli, bool basic) {
}
{
int count = 100;
int count = 10;
while (count--) {
auto res = cli.Get("/get");
auto res = cli.Get("/httpbin/get");
EXPECT_EQ(200, res->status);
}
}
}
#if 0
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
TEST(KeepAliveTest, NoSSLWithBasic) {
Client cli("httpbin.org");
Client cli("nghttp2.org");
KeepAliveTest(cli, true);
}
TEST(KeepAliveTest, SSLWithBasic) {
SSLClient cli("httpbin.org");
SSLClient cli("nghttp2.org");
KeepAliveTest(cli, true);
}
TEST(KeepAliveTest, NoSSLWithDigest) {
Client cli("httpbin.org");
Client cli("nghttp2.org");
KeepAliveTest(cli, false);
}
TEST(KeepAliveTest, SSLWithDigest) {
SSLClient cli("httpbin.org");
SSLClient cli("nghttp2.org");
KeepAliveTest(cli, false);
}
#endif
#endif