Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add timeout to http filters #48119

Merged
merged 1 commit into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/core/httprequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class HttpRequest : public QObject
virtual void setIgnorePolicies(bool on) = 0;
virtual void setTrustConnectHost(bool on) = 0;
virtual void setIgnoreTlsErrors(bool on) = 0;
virtual void setTimeout(int msecs) = 0;

virtual void start(const QString &method, const QUrl &uri, const HttpHeaders &headers) = 0;
virtual void beginResponse(int code, const QByteArray &reason, const HttpHeaders &headers) = 0;
Expand Down
26 changes: 26 additions & 0 deletions src/core/zhttprequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class ZhttpRequest::Private : public QObject
bool ignorePolicies;
bool trustConnectHost;
bool ignoreTlsErrors;
int timeout;
bool sendBodyAfterAck;
QVariant passthrough;
QString requestMethod;
Expand Down Expand Up @@ -101,10 +102,12 @@ class ZhttpRequest::Private : public QObject
ErrorCondition errorCondition;
RTimer *expireTimer;
RTimer *keepAliveTimer;
RTimer *finishTimer;
bool multi;
bool quiet;
Connection expTimerConnection;
Connection keepAliveTimerConnection;
Connection finishTimerConnection;
DeferCall deferCall;

Private(ZhttpRequest *_q) :
Expand All @@ -118,6 +121,7 @@ class ZhttpRequest::Private : public QObject
ignorePolicies(false),
trustConnectHost(false),
ignoreTlsErrors(false),
timeout(0),
sendBodyAfterAck(false),
inSeq(0),
outSeq(0),
Expand All @@ -135,6 +139,7 @@ class ZhttpRequest::Private : public QObject
errored(false),
expireTimer(0),
keepAliveTimer(0),
finishTimer(0),
multi(false),
quiet(false)
{
Expand Down Expand Up @@ -176,6 +181,14 @@ class ZhttpRequest::Private : public QObject
keepAliveTimer = 0;
}

if(finishTimer)
{
finishTimerConnection.disconnect();
finishTimer->setParent(0);
DeferCall::deleteLater(finishTimer);
finishTimer = 0;
}

if(manager)
{
manager->unregisterKeepAlive(q);
Expand Down Expand Up @@ -281,6 +294,14 @@ class ZhttpRequest::Private : public QObject
{
state = ClientStarting;

if(timeout > 0)
{
finishTimer = new RTimer;
finishTimerConnection = finishTimer->timeout.connect(boost::bind(&Private::expire_timeout, this));
finishTimer->setSingleShot(true);
finishTimer->start(timeout);
}

refreshTimeout();
update();
}
Expand Down Expand Up @@ -1231,6 +1252,11 @@ void ZhttpRequest::setIgnoreTlsErrors(bool on)
d->ignoreTlsErrors = on;
}

void ZhttpRequest::setTimeout(int msecs)
{
d->timeout = msecs;
}

void ZhttpRequest::setIsTls(bool on)
{
d->requestUri.setScheme(on ? "https" : "http");
Expand Down
3 changes: 3 additions & 0 deletions src/core/zhttprequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "httprequest.h"
#include <boost/signals2.hpp>

#define TIMERS_PER_ZHTTPREQUEST 3

using Connection = boost::signals2::scoped_connection;

class ZhttpRequestPacket;
Expand Down Expand Up @@ -89,6 +91,7 @@ class ZhttpRequest : public HttpRequest
virtual void setIgnorePolicies(bool on);
virtual void setTrustConnectHost(bool on);
virtual void setIgnoreTlsErrors(bool on);
virtual void setTimeout(int msecs);

virtual void start(const QString &method, const QUrl &uri, const HttpHeaders &headers);
virtual void beginResponse(int code, const QByteArray &reason, const HttpHeaders &headers);
Expand Down
31 changes: 30 additions & 1 deletion src/handler/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "zhttpmanager.h"
#include "zhttprequest.h"

#define REQUEST_TIMEOUT_SECS 10

namespace {

class SkipSelfFilter : public Filter, public Filter::MessageFilter
Expand Down Expand Up @@ -378,6 +380,9 @@ class HttpFilterInner

void startRequest()
{
// set timeout since filters should be fast
req->setTimeout(REQUEST_TIMEOUT_SECS * 1000);

req->start("POST", uri, headers);

if(mode == HttpFilter::Modify)
Expand Down Expand Up @@ -453,8 +458,32 @@ class HttpFilterInner

void req_error()
{
const char *s;

switch(req->errorCondition())
{
case HttpRequest::ErrorConnect:
s = "connection refused";
break;
case HttpRequest::ErrorConnectTimeout:
s = "connection timed out";
break;
case HttpRequest::ErrorTls:
s = "tls error";
break;
case HttpRequest::ErrorDisconnected:
s = "disconnected";
break;
case HttpRequest::ErrorTimeout:
s = "request timed out";
break;
default:
s = "general error";
break;
}

Filter::MessageFilter::Result r;
r.errorMessage = "network request failed";
r.errorMessage = QString("network request failed: %1").arg(s);
finished(r);
}
};
Expand Down
4 changes: 2 additions & 2 deletions src/handler/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
#include <QMetaType>
#include <QUrl>
#include <boost/signals2.hpp>
#include "zhttprequest.h"
#include "ratelimiter.h"

#define MESSAGEFILTERSTACK_SIZE_MAX 5

// 2 timers per zhttprequest
#define TIMERS_PER_MESSAGEFILTERSTACK (2 * MESSAGEFILTERSTACK_SIZE_MAX)
#define TIMERS_PER_MESSAGEFILTERSTACK (TIMERS_PER_ZHTTPREQUEST * MESSAGEFILTERSTACK_SIZE_MAX)

class ZhttpManager;

Expand Down
7 changes: 4 additions & 3 deletions src/handler/httpsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@
#include <boost/signals2.hpp>

// each session can have a bunch of timers:
// 2 per incoming zhttprequest
// 2 per outgoing zhttprequest
// incoming request
// outgoing request
// 2 additional timers
// filter timers
#define TIMERS_PER_HTTPSESSION (10 + TIMERS_PER_MESSAGEFILTERSTACK)
// a few more just in case
#define TIMERS_PER_HTTPSESSION ((TIMERS_PER_ZHTTPREQUEST * 2) + 2 + TIMERS_PER_MESSAGEFILTERSTACK + 4)

using Connection = boost::signals2::scoped_connection;

Expand Down
5 changes: 5 additions & 0 deletions src/proxy/testhttprequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ void TestHttpRequest::setIgnoreTlsErrors(bool on)
Q_UNUSED(on);
}

void TestHttpRequest::setTimeout(int msecs)
{
Q_UNUSED(msecs);
}

void TestHttpRequest::start(const QString &method, const QUrl &uri, const HttpHeaders &headers)
{
assert(d->state == Private::Idle);
Expand Down
1 change: 1 addition & 0 deletions src/proxy/testhttprequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class TestHttpRequest : public HttpRequest
virtual void setIgnorePolicies(bool on);
virtual void setTrustConnectHost(bool on);
virtual void setIgnoreTlsErrors(bool on);
virtual void setTimeout(int msecs);

virtual void start(const QString &method, const QUrl &uri, const HttpHeaders &headers);
virtual void beginResponse(int code, const QByteArray &reason, const HttpHeaders &headers);
Expand Down
Loading