1 #include "networkhttpreply.h"
3 NetworkHttpReply::NetworkHttpReply(const HttpRequest &req, Http &http)
4 : http(http), req(req), retryCount(0) {
5 if (req.url.isEmpty()) {
6 qWarning() << "Empty URL";
9 networkReply = http.networkReply(req);
10 setParent(networkReply);
13 readTimeoutTimer = new QTimer(this);
14 readTimeoutTimer->setInterval(http.getReadTimeout());
15 readTimeoutTimer->setSingleShot(true);
16 connect(readTimeoutTimer, SIGNAL(timeout()), SLOT(readTimeout()), Qt::UniqueConnection);
17 readTimeoutTimer->start();
20 void NetworkHttpReply::setupReply() {
21 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
22 connect(networkReply, &QNetworkReply::errorOccurred, this, &NetworkHttpReply::replyError,
23 Qt::UniqueConnection);
25 connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
26 SLOT(replyError(QNetworkReply::NetworkError)), Qt::UniqueConnection);
28 connect(networkReply, SIGNAL(finished()), SLOT(replyFinished()), Qt::UniqueConnection);
29 connect(networkReply, SIGNAL(downloadProgress(qint64, qint64)),
30 SLOT(downloadProgress(qint64, qint64)), Qt::UniqueConnection);
33 QString NetworkHttpReply::errorMessage() {
34 return url().toString() + QLatin1Char(' ') + QString::number(statusCode()) + QLatin1Char(' ') +
38 void NetworkHttpReply::emitError() {
39 const QString msg = errorMessage();
40 #ifndef QT_NO_DEBUG_OUTPUT
41 qDebug() << "Http:" << msg;
42 if (!req.body.isEmpty()) qDebug() << "Http:" << req.body;
48 void NetworkHttpReply::emitFinished() {
49 readTimeoutTimer->stop();
51 // disconnect to avoid replyFinished() from being called
52 networkReply->disconnect();
57 // this will also delete this object and HttpReply as the QNetworkReply is their parent
58 networkReply->deleteLater();
61 void NetworkHttpReply::replyFinished() {
62 #if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
63 QUrl redirection = networkReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
64 if (redirection.isValid()) {
65 HttpRequest redirectReq;
66 if (redirection.isRelative()) redirection = networkReply->url().resolved(redirection);
67 redirectReq.url = redirection;
68 qDebug() << "Redirected to" << redirectReq.url;
69 redirectReq.operation = req.operation;
70 redirectReq.body = req.body;
71 redirectReq.offset = req.offset;
72 QNetworkReply *redirectReply = http.networkReply(redirectReq);
73 setParent(redirectReply);
74 networkReply->deleteLater();
75 networkReply = redirectReply;
77 readTimeoutTimer->start();
83 bytes = networkReply->readAll();
86 #ifndef QT_NO_DEBUG_OUTPUT
87 if (!networkReply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool())
88 qDebug() << statusCode() << networkReply->url().toString();
90 qDebug() << "CACHE" << networkReply->url().toString();
97 void NetworkHttpReply::replyError(QNetworkReply::NetworkError code) {
99 const int status = statusCode();
100 if (retryCount <= http.getMaxRetries() && status >= 500 && status < 600 &&
101 (networkReply->operation() == QNetworkAccessManager::GetOperation ||
102 networkReply->operation() == QNetworkAccessManager::HeadOperation)) {
103 qDebug() << "Retrying" << status << QVariant(req.operation).toString() << req.url;
104 networkReply->disconnect();
105 networkReply->deleteLater();
106 QNetworkReply *retryReply = http.networkReply(req);
107 setParent(retryReply);
108 networkReply = retryReply;
111 readTimeoutTimer->start();
118 void NetworkHttpReply::downloadProgress(qint64 bytesReceived, qint64 /* bytesTotal */) {
119 // qDebug() << "Downloading" << bytesReceived << bytesTotal << networkReply->url();
120 if (bytesReceived > 0 && readTimeoutTimer->isActive()) {
121 readTimeoutTimer->stop();
122 disconnect(networkReply, SIGNAL(downloadProgress(qint64, qint64)), this,
123 SLOT(downloadProgress(qint64, qint64)));
127 void NetworkHttpReply::readTimeout() {
128 qDebug() << "Timeout" << req.url;
130 if (!networkReply) return;
132 bool shouldRetry = (networkReply->operation() == QNetworkAccessManager::GetOperation ||
133 networkReply->operation() == QNetworkAccessManager::HeadOperation) &&
134 retryCount < http.getMaxRetries();
136 networkReply->disconnect();
137 networkReply->abort();
138 networkReply->deleteLater();
142 emit finished(*this);
147 QNetworkReply *retryReply = http.networkReply(req);
148 setParent(retryReply);
149 networkReply = retryReply;
151 readTimeoutTimer->start();
154 QUrl NetworkHttpReply::url() const {
155 return networkReply->url();
158 int NetworkHttpReply::statusCode() const {
159 return networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
162 QString NetworkHttpReply::reasonPhrase() const {
163 return networkReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
166 const QList<QNetworkReply::RawHeaderPair> NetworkHttpReply::headers() const {
167 return networkReply->rawHeaderPairs();
170 QByteArray NetworkHttpReply::header(const QByteArray &headerName) const {
171 return networkReply->rawHeader(headerName);
174 QByteArray NetworkHttpReply::body() const {