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 connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
22 SLOT(replyError(QNetworkReply::NetworkError)), Qt::UniqueConnection);
23 connect(networkReply, SIGNAL(finished()), SLOT(replyFinished()), Qt::UniqueConnection);
24 connect(networkReply, SIGNAL(downloadProgress(qint64, qint64)),
25 SLOT(downloadProgress(qint64, qint64)), Qt::UniqueConnection);
28 QString NetworkHttpReply::errorMessage() {
29 return url().toString() + QLatin1Char(' ') + QString::number(statusCode()) + QLatin1Char(' ') +
33 void NetworkHttpReply::emitError() {
34 const QString msg = errorMessage();
35 #ifndef QT_NO_DEBUG_OUTPUT
36 qDebug() << "Http:" << msg;
37 if (!req.body.isEmpty()) qDebug() << "Http:" << req.body;
43 void NetworkHttpReply::emitFinished() {
44 readTimeoutTimer->stop();
46 // disconnect to avoid replyFinished() from being called
47 networkReply->disconnect();
52 // this will also delete this object and HttpReply as the QNetworkReply is their parent
53 networkReply->deleteLater();
56 void NetworkHttpReply::replyFinished() {
57 QUrl redirection = networkReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
58 if (redirection.isValid()) {
59 HttpRequest redirectReq;
60 if (redirection.isRelative()) redirection = networkReply->url().resolved(redirection);
61 redirectReq.url = redirection;
62 qDebug() << "Redirected to" << redirectReq.url;
63 redirectReq.operation = req.operation;
64 redirectReq.body = req.body;
65 redirectReq.offset = req.offset;
66 QNetworkReply *redirectReply = http.networkReply(redirectReq);
67 setParent(redirectReply);
68 networkReply->deleteLater();
69 networkReply = redirectReply;
71 readTimeoutTimer->start();
76 bytes = networkReply->readAll();
79 #ifndef QT_NO_DEBUG_OUTPUT
80 if (!networkReply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool())
81 qDebug() << statusCode() << networkReply->url().toString();
83 qDebug() << "CACHE" << networkReply->url().toString();
90 void NetworkHttpReply::replyError(QNetworkReply::NetworkError code) {
92 const int status = statusCode();
93 if (retryCount <= http.getMaxRetries() && status >= 500 && status < 600 &&
94 (networkReply->operation() == QNetworkAccessManager::GetOperation ||
95 networkReply->operation() == QNetworkAccessManager::HeadOperation)) {
96 qDebug() << "Retrying" << status << QVariant(req.operation).toString() << req.url;
97 networkReply->disconnect();
98 networkReply->deleteLater();
99 QNetworkReply *retryReply = http.networkReply(req);
100 setParent(retryReply);
101 networkReply = retryReply;
104 readTimeoutTimer->start();
111 void NetworkHttpReply::downloadProgress(qint64 bytesReceived, qint64 /* bytesTotal */) {
112 // qDebug() << "Downloading" << bytesReceived << bytesTotal << networkReply->url();
113 if (bytesReceived > 0 && readTimeoutTimer->isActive()) {
114 readTimeoutTimer->stop();
115 disconnect(networkReply, SIGNAL(downloadProgress(qint64, qint64)), this,
116 SLOT(downloadProgress(qint64, qint64)));
120 void NetworkHttpReply::readTimeout() {
121 qDebug() << "Timeout" << req.url;
123 if (!networkReply) return;
125 bool shouldRetry = (networkReply->operation() == QNetworkAccessManager::GetOperation ||
126 networkReply->operation() == QNetworkAccessManager::HeadOperation) &&
127 retryCount < http.getMaxRetries();
129 networkReply->disconnect();
130 networkReply->abort();
131 networkReply->deleteLater();
135 emit finished(*this);
140 QNetworkReply *retryReply = http.networkReply(req);
141 setParent(retryReply);
142 networkReply = retryReply;
144 readTimeoutTimer->start();
147 QUrl NetworkHttpReply::url() const {
148 return networkReply->url();
151 int NetworkHttpReply::statusCode() const {
152 return networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
155 QString NetworkHttpReply::reasonPhrase() const {
156 return networkReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
159 const QList<QNetworkReply::RawHeaderPair> NetworkHttpReply::headers() const {
160 return networkReply->rawHeaderPairs();
163 QByteArray NetworkHttpReply::header(const QByteArray &headerName) const {
164 return networkReply->rawHeader(headerName);
167 QByteArray NetworkHttpReply::body() const {