Alternative implementation of solution for issue #1756 (allow specific HTTP timeout)

This commit is contained in:
Matthias Koefferlein 2024-06-30 19:33:12 +02:00
parent 564861abe1
commit 54aeea54ca
5 changed files with 74 additions and 4 deletions

View File

@ -22,6 +22,7 @@
#include "tlHttpStream.h"
#include "tlEnv.h"
namespace tl
{
@ -52,4 +53,22 @@ HttpErrorException::format_error (const std::string &em, int ec, const std::stri
return msg;
}
// ---------------------------------------------------------------
// Common implementation
double
InputHttpStream::get_default_timeout ()
{
// default timeout
double timeout_value = 10.0;
std::string timeout = tl::get_env ("KLAYOUT_HTTP_TIMEOUT");
if (! timeout.empty ()) {
tl::Extractor ex (timeout.c_str ());
ex.try_read (timeout_value);
}
return timeout_value;
}
}

View File

@ -98,6 +98,11 @@ public:
*/
virtual ~InputHttpStream ();
/**
* @brief Gets the timeout value (in seconds)
*/
static double get_default_timeout ();
/**
* @brief Sets the credential provider
*/

View File

@ -33,6 +33,7 @@
#include "tlProgress.h"
#include "tlFileUtils.h"
#include "tlUri.h"
#include "tlString.h"
#if !defined(_MSC_VER)
# include <sys/time.h>
@ -1282,7 +1283,7 @@ void CurlNetworkManager::tick ()
// InputHttpStreamPrivateData implementation
InputHttpStreamPrivateData::InputHttpStreamPrivateData (InputHttpStream *stream, const std::string &url)
: m_timeout (10.0), mp_stream (stream)
: m_timeout (InputHttpStream::get_default_timeout ()), mp_stream (stream)
{
m_sent = false;
m_ready = false;
@ -1391,7 +1392,13 @@ InputHttpStreamPrivateData::read (char *b, size_t n)
}
tl::Clock start_time = tl::Clock::current ();
while (n > m_connection->read_available () && ! m_connection->finished () && (m_timeout <= 0.0 || (tl::Clock::current() - start_time).seconds () < m_timeout) && ! tl::CurlNetworkManager::instance ()->has_reply ()) {
while (n > m_connection->read_available () && ! m_connection->finished () && ! tl::CurlNetworkManager::instance ()->has_reply ()) {
// Check for timeout
if (m_timeout > 0.0 && (tl::Clock::current() - start_time).seconds () >= m_timeout) {
throw tl::HttpErrorException (tl::sprintf (tl::to_string (tr ("Connection timed out (timeout is %.1fs)")), m_timeout), 0, m_connection->url ());
}
mp_stream->tick ();
if (m_progress.get ()) { // might have been reset by tick()
++*m_progress;

View File

@ -28,6 +28,7 @@
#include "tlObject.h"
#include "tlTimer.h"
#include "tlSleep.h"
#include "tlString.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
@ -256,7 +257,7 @@ static QNetworkAccessManager *s_network_manager (0);
static AuthenticationHandler *s_auth_handler (0);
InputHttpStreamPrivateData::InputHttpStreamPrivateData (InputHttpStream *stream, const std::string &url)
: m_url (url), mp_reply (0), m_request ("GET"), mp_buffer (0), mp_resend_timer (new QTimer (this)), m_timeout (10.0), mp_stream (stream)
: m_url (url), mp_reply (0), m_request ("GET"), mp_buffer (0), mp_resend_timer (new QTimer (this)), m_timeout (InputHttpStream::get_default_timeout ()), mp_stream (stream)
{
if (! s_network_manager) {
@ -466,7 +467,7 @@ InputHttpStreamPrivateData::read (char *b, size_t n)
// Reason for this may be HTTPS initialization failure (OpenSSL)
std::string em = tl::to_string (QObject::tr ("Request creation failed"));
std::string em = tl::sprintf (tl::to_string (QObject::tr ("Request creation failed (timeout is %.1fs)")), m_timeout);
if (tl::verbosity() >= 30) {
tl::info << "HTTP request creation failed";
}

View File

@ -25,6 +25,7 @@
#include "tlUnitTest.h"
#include "tlTimer.h"
#include "tlStream.h"
#include "tlEnv.h"
static std::string test_url1 ("http://www.klayout.org/svn-public/klayout-resources/trunk/testdata/text");
static std::string test_url1_gz ("http://www.klayout.org/svn-public/klayout-resources/trunk/testdata2/text.gz");
@ -153,3 +154,40 @@ TEST(5)
EXPECT_EQ (res, "hello, world.\n");
}
// tl::InputHttpStream timeout
TEST(6)
{
if (! tl::InputHttpStream::is_available ()) {
throw tl::CancelException ();
}
{
tl::set_env ("KLAYOUT_HTTP_TIMEOUT", "");
tl::InputHttpStream stream (test_url1);
stream.set_timeout (0.001); // probably too fast :)
try {
char b[100];
stream.read (b, sizeof (b));
EXPECT_EQ (true, false);
} catch (tl::HttpErrorException &ex) {
tl::info << "Got exception (expected): " << ex.msg ();
}
}
{
tl::set_env ("KLAYOUT_HTTP_TIMEOUT", "0.001");
tl::InputHttpStream stream (test_url1);
try {
char b[100];
stream.read (b, sizeof (b));
EXPECT_EQ (true, false);
} catch (tl::HttpErrorException &ex) {
tl::info << "Got exception (expected): " << ex.msg ();
}
}
tl::unset_env ("KLAYOUT_HTTP_TIMEOUT");
}