Merge pull request #295 from yhirose/timeout

Fix #294
This commit is contained in:
yhirose 2019-12-18 17:57:23 -05:00 committed by GitHub
commit ae43c96984
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 51 deletions

View File

@ -301,7 +301,7 @@ res = cli.Options("/resource/foo");
### Connection Timeout ### Connection Timeout
```c++ ```c++
httplib::Client cli("localhost", 8080, 5); // timeouts in 5 seconds cli.set_timeout_sec(5); // timeouts in 5 seconds
``` ```
### With Progress Callback ### With Progress Callback

View File

@ -614,7 +614,7 @@ private:
class Client { class Client {
public: public:
explicit Client(const char *host, int port = 80, time_t timeout_sec = 300); explicit Client(const char *host, int port = 80);
virtual ~Client(); virtual ~Client();
@ -734,6 +734,8 @@ public:
bool send(const std::vector<Request> &requests, bool send(const std::vector<Request> &requests,
std::vector<Response> &responses); std::vector<Response> &responses);
void set_timeout_sec(time_t timeout_sec);
void set_keep_alive_max_count(size_t count); void set_keep_alive_max_count(size_t count);
void set_read_timeout(time_t sec, time_t usec); void set_read_timeout(time_t sec, time_t usec);
@ -752,15 +754,17 @@ protected:
const std::string host_; const std::string host_;
const int port_; const int port_;
time_t timeout_sec_;
const std::string host_and_port_; const std::string host_and_port_;
size_t keep_alive_max_count_;
time_t read_timeout_sec_; // Options
time_t read_timeout_usec_; time_t timeout_sec_ = 300;
bool follow_location_; size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
std::string username_; std::string username_;
std::string password_; std::string password_;
bool compress_; bool follow_location_ = false;
bool compress_ = false;
std::string interface_; std::string interface_;
private: private:
@ -852,7 +856,7 @@ private:
class SSLClient : public Client { class SSLClient : public Client {
public: public:
SSLClient(const char *host, int port = 443, time_t timeout_sec = 300, SSLClient(const char *host, int port = 443,
const char *client_cert_path = nullptr, const char *client_cert_path = nullptr,
const char *client_key_path = nullptr); const char *client_key_path = nullptr);
@ -884,6 +888,8 @@ private:
SSL_CTX *ctx_; SSL_CTX *ctx_;
std::mutex ctx_mutex_; std::mutex ctx_mutex_;
std::vector<std::string> host_components_; std::vector<std::string> host_components_;
// Options
std::string ca_cert_file_path_; std::string ca_cert_file_path_;
std::string ca_cert_dir_path_; std::string ca_cert_dir_path_;
bool server_certificate_verification_ = false; bool server_certificate_verification_ = false;
@ -3371,13 +3377,9 @@ inline bool Server::process_and_close_socket(socket_t sock) {
} }
// HTTP client implementation // HTTP client implementation
inline Client::Client(const char *host, int port, time_t timeout_sec) inline Client::Client(const char *host, int port)
: host_(host), port_(port), timeout_sec_(timeout_sec), : host_(host), port_(port),
host_and_port_(host_ + ":" + std::to_string(port_)), host_and_port_(host_ + ":" + std::to_string(port_)) {}
keep_alive_max_count_(CPPHTTPLIB_KEEPALIVE_MAX_COUNT),
read_timeout_sec_(CPPHTTPLIB_READ_TIMEOUT_SECOND),
read_timeout_usec_(CPPHTTPLIB_READ_TIMEOUT_USECOND),
follow_location_(false), compress_(false) {}
inline Client::~Client() {} inline Client::~Client() {}
@ -4004,6 +4006,10 @@ inline std::shared_ptr<Response> Client::Options(const char *path,
return send(req, *res) ? res : nullptr; return send(req, *res) ? res : nullptr;
} }
inline void Client::set_timeout_sec(time_t timeout_sec) {
timeout_sec_ = timeout_sec;
}
inline void Client::set_keep_alive_max_count(size_t count) { inline void Client::set_keep_alive_max_count(size_t count) {
keep_alive_max_count_ = count; keep_alive_max_count_ = count;
} }
@ -4243,10 +4249,10 @@ inline bool SSLServer::process_and_close_socket(socket_t sock) {
} }
// SSL HTTP client implementation // SSL HTTP client implementation
inline SSLClient::SSLClient(const char *host, int port, time_t timeout_sec, inline SSLClient::SSLClient(const char *host, int port,
const char *client_cert_path, const char *client_cert_path,
const char *client_key_path) const char *client_key_path)
: Client(host, port, timeout_sec) { : Client(host, port) {
ctx_ = SSL_CTX_new(SSLv23_client_method()); ctx_ = SSL_CTX_new(SSLv23_client_method());
detail::split(&host_[0], &host_[host_.size()], '.', detail::split(&host_[0], &host_[host_.size()], '.',

View File

@ -204,15 +204,15 @@ TEST(ParseHeaderValueTest, Range) {
TEST(ChunkedEncodingTest, FromHTTPWatch) { TEST(ChunkedEncodingTest, FromHTTPWatch) {
auto host = "www.httpwatch.com"; auto host = "www.httpwatch.com";
auto sec = 2;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443; auto port = 443;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 80; auto port = 80;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(2);
auto res = auto res =
cli.Get("/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137"); cli.Get("/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137");
@ -227,15 +227,15 @@ TEST(ChunkedEncodingTest, FromHTTPWatch) {
TEST(ChunkedEncodingTest, WithContentReceiver) { TEST(ChunkedEncodingTest, WithContentReceiver) {
auto host = "www.httpwatch.com"; auto host = "www.httpwatch.com";
auto sec = 2;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443; auto port = 443;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 80; auto port = 80;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(2);
std::string body; std::string body;
auto res = auto res =
@ -255,15 +255,15 @@ TEST(ChunkedEncodingTest, WithContentReceiver) {
TEST(ChunkedEncodingTest, WithResponseHandlerAndContentReceiver) { TEST(ChunkedEncodingTest, WithResponseHandlerAndContentReceiver) {
auto host = "www.httpwatch.com"; auto host = "www.httpwatch.com";
auto sec = 2;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443; auto port = 443;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 80; auto port = 80;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(2);
std::string body; std::string body;
auto res = cli.Get( auto res = cli.Get(
@ -287,15 +287,15 @@ TEST(ChunkedEncodingTest, WithResponseHandlerAndContentReceiver) {
TEST(RangeTest, FromHTTPBin) { TEST(RangeTest, FromHTTPBin) {
auto host = "httpbin.org"; auto host = "httpbin.org";
auto sec = 5;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443; auto port = 443;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 80; auto port = 80;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(5);
{ {
httplib::Headers headers; httplib::Headers headers;
@ -347,15 +347,15 @@ TEST(RangeTest, FromHTTPBin) {
TEST(ConnectionErrorTest, InvalidHost) { TEST(ConnectionErrorTest, InvalidHost) {
auto host = "-abcde.com"; auto host = "-abcde.com";
auto sec = 2;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443; auto port = 443;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 80; auto port = 80;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(2);
auto res = cli.Get("/"); auto res = cli.Get("/");
ASSERT_TRUE(res == nullptr); ASSERT_TRUE(res == nullptr);
@ -363,15 +363,15 @@ TEST(ConnectionErrorTest, InvalidHost) {
TEST(ConnectionErrorTest, InvalidPort) { TEST(ConnectionErrorTest, InvalidPort) {
auto host = "localhost"; auto host = "localhost";
auto sec = 2;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 44380; auto port = 44380;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 8080; auto port = 8080;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(2);
auto res = cli.Get("/"); auto res = cli.Get("/");
ASSERT_TRUE(res == nullptr); ASSERT_TRUE(res == nullptr);
@ -379,15 +379,15 @@ TEST(ConnectionErrorTest, InvalidPort) {
TEST(ConnectionErrorTest, Timeout) { TEST(ConnectionErrorTest, Timeout) {
auto host = "google.com"; auto host = "google.com";
auto sec = 2;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 44380; auto port = 44380;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 8080; auto port = 8080;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(2);
auto res = cli.Get("/"); auto res = cli.Get("/");
ASSERT_TRUE(res == nullptr); ASSERT_TRUE(res == nullptr);
@ -395,15 +395,15 @@ TEST(ConnectionErrorTest, Timeout) {
TEST(CancelTest, NoCancel) { TEST(CancelTest, NoCancel) {
auto host = "httpbin.org"; auto host = "httpbin.org";
auto sec = 5;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443; auto port = 443;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 80; auto port = 80;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(5);
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); ASSERT_TRUE(res != nullptr);
@ -413,31 +413,31 @@ TEST(CancelTest, NoCancel) {
TEST(CancelTest, WithCancelSmallPayload) { TEST(CancelTest, WithCancelSmallPayload) {
auto host = "httpbin.org"; auto host = "httpbin.org";
auto sec = 5;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443; auto port = 443;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 80; auto port = 80;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #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; });
cli.set_timeout_sec(5);
ASSERT_TRUE(res == nullptr); ASSERT_TRUE(res == nullptr);
} }
TEST(CancelTest, WithCancelLargePayload) { TEST(CancelTest, WithCancelLargePayload) {
auto host = "httpbin.org"; auto host = "httpbin.org";
auto sec = 5;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
auto port = 443; auto port = 443;
httplib::SSLClient cli(host, port, sec); httplib::SSLClient cli(host, port);
#else #else
auto port = 80; auto port = 80;
httplib::Client cli(host, port, sec); httplib::Client cli(host, port);
#endif #endif
cli.set_timeout_sec(5);
uint32_t count = 0; uint32_t count = 0;
httplib::Headers headers; httplib::Headers headers;
@ -2090,9 +2090,10 @@ TEST(SSLClientServerTest, ClientCertPresent) {
thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); }); thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
msleep(1); msleep(1);
httplib::SSLClient cli(HOST, PORT, 30, CLIENT_CERT_FILE, httplib::SSLClient cli(HOST, PORT, CLIENT_CERT_FILE,
CLIENT_PRIVATE_KEY_FILE); CLIENT_PRIVATE_KEY_FILE);
auto res = cli.Get("/test"); auto res = cli.Get("/test");
cli.set_timeout_sec(30);
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
ASSERT_EQ(200, res->status); ASSERT_EQ(200, res->status);
@ -2109,8 +2110,9 @@ TEST(SSLClientServerTest, ClientCertMissing) {
thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); }); thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
msleep(1); msleep(1);
httplib::SSLClient cli(HOST, PORT, 30); httplib::SSLClient cli(HOST, PORT);
auto res = cli.Get("/test"); auto res = cli.Get("/test");
cli.set_timeout_sec(30);
ASSERT_TRUE(res == nullptr); ASSERT_TRUE(res == nullptr);
svr.stop(); svr.stop();
@ -2130,9 +2132,10 @@ TEST(SSLClientServerTest, TrustDirOptional) {
thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); }); thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
msleep(1); msleep(1);
httplib::SSLClient cli(HOST, PORT, 30, CLIENT_CERT_FILE, httplib::SSLClient cli(HOST, PORT, CLIENT_CERT_FILE,
CLIENT_PRIVATE_KEY_FILE); CLIENT_PRIVATE_KEY_FILE);
auto res = cli.Get("/test"); auto res = cli.Get("/test");
cli.set_timeout_sec(30);
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
ASSERT_EQ(200, res->status); ASSERT_EQ(200, res->status);