Skip to content

Commit

Permalink
Another simpler implementation of #890 (#891)
Browse files Browse the repository at this point in the history
  • Loading branch information
yhirose authored Apr 2, 2021
1 parent b845425 commit 6ff84d3
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 11 deletions.
106 changes: 106 additions & 0 deletions httplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -668,9 +668,18 @@ class Server {

Server &set_keep_alive_max_count(size_t count);
Server &set_keep_alive_timeout(time_t sec);

Server &set_read_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
Server &set_read_timeout(const std::chrono::duration<Rep, Period> &duration);

Server &set_write_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
Server &set_write_timeout(const std::chrono::duration<Rep, Period> &duration);

Server &set_idle_interval(time_t sec, time_t usec = 0);
template <class Rep, class Period>
Server &set_idle_interval(const std::chrono::duration<Rep, Period> &duration);

Server &set_payload_max_length(size_t length);

Expand Down Expand Up @@ -966,8 +975,16 @@ class ClientImpl {
void set_socket_options(SocketOptions socket_options);

void set_connection_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
void set_connection_timeout(const std::chrono::duration<Rep, Period> &duration);

void set_read_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
void set_read_timeout(const std::chrono::duration<Rep, Period> &duration);

void set_write_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
void set_write_timeout(const std::chrono::duration<Rep, Period> &duration);

void set_basic_auth(const char *username, const char *password);
void set_bearer_token_auth(const char *token);
Expand Down Expand Up @@ -1268,8 +1285,16 @@ class Client {
void set_socket_options(SocketOptions socket_options);

void set_connection_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
void set_connection_timeout(const std::chrono::duration<Rep, Period> &duration);

void set_read_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
void set_read_timeout(const std::chrono::duration<Rep, Period> &duration);

void set_write_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
void set_write_timeout(const std::chrono::duration<Rep, Period> &duration);

void set_basic_auth(const char *username, const char *password);
void set_bearer_token_auth(const char *token);
Expand Down Expand Up @@ -3804,6 +3829,15 @@ class ContentProviderAdapter {
ContentProviderWithoutLength content_provider_;
};

template <typename T, typename U>
inline void duration_to_sec_and_usec(const T &duration, U callback) {
auto sec = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
auto usec = std::chrono::duration_cast<std::chrono::microseconds>(
duration - std::chrono::seconds(sec))
.count();
callback(sec, usec);
}

} // namespace detail

// Header utilities
Expand Down Expand Up @@ -4381,20 +4415,47 @@ inline Server &Server::set_read_timeout(time_t sec, time_t usec) {
return *this;
}

template <class Rep, class Period>
inline Server &Server::set_read_timeout(
const std::chrono::duration<Rep, Period> &duration) {
detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) {
set_read_timeout(sec, usec);
});
return *this;
}

inline Server &Server::set_write_timeout(time_t sec, time_t usec) {
write_timeout_sec_ = sec;
write_timeout_usec_ = usec;

return *this;
}

template <class Rep, class Period>
inline Server &Server::set_write_timeout(
const std::chrono::duration<Rep, Period> &duration) {
detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) {
set_write_timeout(sec, usec);
});
return *this;
}

inline Server &Server::set_idle_interval(time_t sec, time_t usec) {
idle_interval_sec_ = sec;
idle_interval_usec_ = usec;

return *this;
}

template <class Rep, class Period>
inline Server &Server::set_idle_interval(
const std::chrono::duration<Rep, Period> &duration) {
detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) {
set_idle_interval(sec, usec);
});
return *this;
}

inline Server &Server::set_payload_max_length(size_t length) {
payload_max_length_ = length;

Expand Down Expand Up @@ -6273,16 +6334,40 @@ inline void ClientImpl::set_connection_timeout(time_t sec, time_t usec) {
connection_timeout_usec_ = usec;
}

template <class Rep, class Period>
inline void ClientImpl::set_connection_timeout(
const std::chrono::duration<Rep, Period> &duration) {
detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) {
set_connection_timeout(sec, usec);
});
}

inline void ClientImpl::set_read_timeout(time_t sec, time_t usec) {
read_timeout_sec_ = sec;
read_timeout_usec_ = usec;
}

template <class Rep, class Period>
inline void ClientImpl::set_read_timeout(
const std::chrono::duration<Rep, Period> &duration) {
detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) {
set_read_timeout(sec, usec);
});
}

inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) {
write_timeout_sec_ = sec;
write_timeout_usec_ = usec;
}

template <class Rep, class Period>
inline void ClientImpl::set_write_timeout(
const std::chrono::duration<Rep, Period> &duration) {
detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) {
set_write_timeout(sec, usec);
});
}

inline void ClientImpl::set_basic_auth(const char *username,
const char *password) {
basic_auth_username_ = username;
Expand Down Expand Up @@ -7372,20 +7457,41 @@ inline void Client::set_default_headers(Headers headers) {
}

inline void Client::set_tcp_nodelay(bool on) { cli_->set_tcp_nodelay(on); }

inline void Client::set_socket_options(SocketOptions socket_options) {
cli_->set_socket_options(std::move(socket_options));
}

inline void Client::set_connection_timeout(time_t sec, time_t usec) {
cli_->set_connection_timeout(sec, usec);
}

template <class Rep, class Period>
inline void Client::set_connection_timeout(
const std::chrono::duration<Rep, Period> &duration) {
cli_->set_connection_timeout(duration);
}

inline void Client::set_read_timeout(time_t sec, time_t usec) {
cli_->set_read_timeout(sec, usec);
}

template <class Rep, class Period>
inline void Client::set_read_timeout(
const std::chrono::duration<Rep, Period> &duration) {
cli_->set_read_timeout(duration);
}

inline void Client::set_write_timeout(time_t sec, time_t usec) {
cli_->set_write_timeout(sec, usec);
}

template <class Rep, class Period>
inline void Client::set_write_timeout(
const std::chrono::duration<Rep, Period> &duration) {
cli_->set_write_timeout(duration);
}

inline void Client::set_basic_auth(const char *username, const char *password) {
cli_->set_basic_auth(username, password);
}
Expand Down
22 changes: 11 additions & 11 deletions test/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ TEST(ConnectionErrorTest, InvalidHost) {
auto port = 80;
Client cli(host, port);
#endif
cli.set_connection_timeout(2);
cli.set_connection_timeout(std::chrono::seconds(2));

auto res = cli.Get("/");
ASSERT_TRUE(!res);
Expand All @@ -540,7 +540,7 @@ TEST(ConnectionErrorTest, InvalidHost2) {
#else
Client cli(host);
#endif
cli.set_connection_timeout(2);
cli.set_connection_timeout(std::chrono::seconds(2));

auto res = cli.Get("/");
ASSERT_TRUE(!res);
Expand All @@ -556,7 +556,7 @@ TEST(ConnectionErrorTest, InvalidPort) {
#else
Client cli(host, port);
#endif
cli.set_connection_timeout(2);
cli.set_connection_timeout(std::chrono::seconds(2));

auto res = cli.Get("/");
ASSERT_TRUE(!res);
Expand All @@ -573,7 +573,7 @@ TEST(ConnectionErrorTest, Timeout) {
auto port = 8080;
Client cli(host, port);
#endif
cli.set_connection_timeout(2);
cli.set_connection_timeout(std::chrono::seconds(2));

auto res = cli.Get("/");
ASSERT_TRUE(!res);
Expand All @@ -590,7 +590,7 @@ TEST(CancelTest, NoCancel) {
auto port = 80;
Client cli(host, port);
#endif
cli.set_connection_timeout(5);
cli.set_connection_timeout(std::chrono::seconds(5));

auto res = cli.Get("/range/32", [](uint64_t, uint64_t) { return true; });
ASSERT_TRUE(res);
Expand All @@ -610,7 +610,7 @@ TEST(CancelTest, WithCancelSmallPayload) {
#endif

auto res = cli.Get("/range/32", [](uint64_t, uint64_t) { return false; });
cli.set_connection_timeout(5);
cli.set_connection_timeout(std::chrono::seconds(5));
ASSERT_TRUE(!res);
EXPECT_EQ(Error::Canceled, res.error());
}
Expand All @@ -625,7 +625,7 @@ TEST(CancelTest, WithCancelLargePayload) {
auto port = 80;
Client cli(host, port);
#endif
cli.set_connection_timeout(5);
cli.set_connection_timeout(std::chrono::seconds(5));

uint32_t count = 0;
auto res = cli.Get("/range/65536",
Expand Down Expand Up @@ -2478,7 +2478,7 @@ TEST_F(ServerTest, SlowPostFail) {
char buffer[64 * 1024];
memset(buffer, 0x42, sizeof(buffer));

cli_.set_write_timeout(0, 0);
cli_.set_write_timeout(std::chrono::seconds(0));
auto res =
cli_.Post("/slowpost", 64 * 1024 * 1024,
[&](size_t /*offset*/, size_t /*length*/, DataSink &sink) {
Expand Down Expand Up @@ -3146,7 +3146,7 @@ static void test_raw_request(const std::string &req,
// bug to reproduce, probably to force the server to process a request
// without a trailing blank line.
const time_t client_read_timeout_sec = 1;
svr.set_read_timeout(client_read_timeout_sec + 1, 0);
svr.set_read_timeout(std::chrono::seconds(client_read_timeout_sec + 1));
bool listen_thread_ok = false;
thread t = thread([&] { listen_thread_ok = svr.listen(HOST, PORT); });
while (!svr.is_running()) {
Expand Down Expand Up @@ -3446,7 +3446,7 @@ TEST(KeepAliveTest, ReadTimeout) {

Client cli("localhost", PORT);
cli.set_keep_alive(true);
cli.set_read_timeout(1);
cli.set_read_timeout(std::chrono::seconds(1));

auto resa = cli.Get("/a");
ASSERT_TRUE(!resa);
Expand Down Expand Up @@ -3583,7 +3583,7 @@ TEST(KeepAliveTest, ReadTimeoutSSL) {
SSLClient cli("localhost", PORT);
cli.enable_server_certificate_verification(false);
cli.set_keep_alive(true);
cli.set_read_timeout(1);
cli.set_read_timeout(std::chrono::seconds(1));

auto resa = cli.Get("/a");
ASSERT_TRUE(!resa);
Expand Down

0 comments on commit 6ff84d3

Please sign in to comment.