diff --git a/include/opendht/http.h b/include/opendht/http.h
index baeeed2e9cfafab4c5e094d1e377b3d9e322f416..f9f086df002c355bec86bff54515408c04bc91a5 100644
--- a/include/opendht/http.h
+++ b/include/opendht/http.h
@@ -114,13 +114,13 @@ public:
     void async_read(size_t bytes, BytesHandlerCb cb);
     void async_read_some(size_t bytes, BytesHandlerCb cb);
 
-    void timeout(const std::chrono::seconds timeout, HandlerCb cb = {});
+    void timeout(const std::chrono::seconds& timeout, HandlerCb cb = {});
     void close();
 
 private:
 
     template<typename T>
-    T wrapCallabck(T cb) const {
+    T wrapCallback(T cb) const {
         return [t=shared_from_this(),cb=std::move(cb)](auto ...params) {
             cb(params...);
         };
@@ -261,6 +261,11 @@ public:
         return resolver_->get_url();
     };
 
+    void timeout(const std::chrono::seconds& timeout, HandlerCb cb = {}) {
+        timeout_ = timeout;
+        timeoutCb_ = cb;
+    }
+
     /** The previous request in case of redirect following */
     std::shared_ptr<Request> getPrevious() const {
         return prev_.lock();
@@ -370,6 +375,9 @@ private:
     std::weak_ptr<Request> prev_;
     unsigned num_redirect {0};
     bool follow_redirect {true};
+
+    HandlerCb timeoutCb_ {};
+    std::chrono::seconds timeout_ {0};
 };
 
 } // namespace http
diff --git a/src/http.cpp b/src/http.cpp
index c0d2f25f876d66133fef3ae4e67b584363ecae6c..af4d851bc59c8ea5c11afba5c857f169daeaf99d 100644
--- a/src/http.cpp
+++ b/src/http.cpp
@@ -619,9 +619,9 @@ Connection::async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, Conn
 #pragma GCC diagnostic pop
 
     if (ssl_socket_)
-        asio::async_connect(ssl_socket_->lowest_layer(), std::move(endpoints), wrapCallabck(std::move(wcb)));
+        asio::async_connect(ssl_socket_->lowest_layer(), std::move(endpoints), wrapCallback(std::move(wcb)));
     else
-        asio::async_connect(*socket_, std::move(endpoints), wrapCallabck(std::move(wcb)));
+        asio::async_connect(*socket_, std::move(endpoints), wrapCallback(std::move(wcb)));
 }
 
 void
@@ -666,8 +666,8 @@ Connection::async_write(BytesHandlerCb cb)
         if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
         return;
     }
-    if (ssl_socket_)  asio::async_write(*ssl_socket_, write_buf_, wrapCallabck(std::move(cb)));
-    else if (socket_) asio::async_write(*socket_, write_buf_, wrapCallabck(std::move(cb)));
+    if (ssl_socket_)  asio::async_write(*ssl_socket_, write_buf_, wrapCallback(std::move(cb)));
+    else if (socket_) asio::async_write(*socket_, write_buf_, wrapCallback(std::move(cb)));
     else if (cb)      ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
 }
 
@@ -679,8 +679,8 @@ Connection::async_read_until(const char* delim, BytesHandlerCb cb)
         if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
         return;
     }
-    if (ssl_socket_)  asio::async_read_until(*ssl_socket_, read_buf_, delim, wrapCallabck(std::move(cb)));
-    else if (socket_) asio::async_read_until(*socket_, read_buf_, delim, wrapCallabck(std::move(cb)));
+    if (ssl_socket_)  asio::async_read_until(*ssl_socket_, read_buf_, delim, wrapCallback(std::move(cb)));
+    else if (socket_) asio::async_read_until(*socket_, read_buf_, delim, wrapCallback(std::move(cb)));
     else if (cb)      ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
 }
 
@@ -692,8 +692,8 @@ Connection::async_read_until(char delim, BytesHandlerCb cb)
         if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
         return;
     }
-    if (ssl_socket_)  asio::async_read_until(*ssl_socket_, read_buf_, delim, wrapCallabck(std::move(cb)));
-    else if (socket_) asio::async_read_until(*socket_, read_buf_, delim, wrapCallabck(std::move(cb)));
+    if (ssl_socket_)  asio::async_read_until(*ssl_socket_, read_buf_, delim, wrapCallback(std::move(cb)));
+    else if (socket_) asio::async_read_until(*socket_, read_buf_, delim, wrapCallback(std::move(cb)));
     else if (cb)      ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
 }
 
@@ -705,8 +705,8 @@ Connection::async_read(size_t bytes, BytesHandlerCb cb)
         if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
         return;
     }
-    if (ssl_socket_)  asio::async_read(*ssl_socket_, read_buf_, asio::transfer_exactly(bytes), wrapCallabck(std::move(cb)));
-    else if (socket_) asio::async_read(*socket_, read_buf_, asio::transfer_exactly(bytes), wrapCallabck(std::move(cb)));
+    if (ssl_socket_)  asio::async_read(*ssl_socket_, read_buf_, asio::transfer_exactly(bytes), wrapCallback(std::move(cb)));
+    else if (socket_) asio::async_read(*socket_, read_buf_, asio::transfer_exactly(bytes), wrapCallback(std::move(cb)));
     else if (cb)      ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
 }
 
@@ -728,15 +728,8 @@ Connection::async_read_some(size_t bytes, BytesHandlerCb cb)
 }
 
 void
-Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
+Connection::timeout(const std::chrono::seconds& timeout, HandlerCb cb)
 {
-    if (!is_open()){
-        if (logger_)
-            logger_->e("[connection:%i] closed, can't timeout", id_);
-        if (cb)
-            cb(asio::error::operation_aborted);
-        return;
-    }
     if (!timeout_timer_)
         timeout_timer_ = std::make_unique<asio::steady_timer>(ctx_);
     timeout_timer_->expires_at(std::chrono::steady_clock::now() + timeout);
@@ -1195,6 +1188,9 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
     else
         conn_ = std::make_shared<Connection>(ctx_, false/*ssl*/, logger_);
 
+    if (conn_ && timeoutCb_)
+        conn_->timeout(timeout_, std::move(timeoutCb_));
+
     // try to connect to any until one works
     std::weak_ptr<Request> wthis = shared_from_this();
     conn_->async_connect(std::move(endpoints), [wthis, cb, isHttps]