From 7f14ad08bb9356f7dbedcde1ab829d0ede89a845 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Wed, 13 Apr 2016 17:00:48 +0200 Subject: [PATCH] Add a way to get Content-Length when using compressed data We are removing the Content-Length header from our QNetworkReply headers from a compressed HTTP reply. A new attribute is added to have access to the original length. Task-number: QTBUG-41840 Change-Id: I4e885e422d4203d63460d49c0eb5f11022003578 Reviewed-by: Edward Welbourne --- src/network/access/qhttpnetworkreply.cpp | 8 +++++++- src/network/access/qhttpnetworkreply_p.h | 2 ++ src/network/access/qhttpthreaddelegate.cpp | 3 +++ src/network/access/qhttpthreaddelegate_p.h | 3 ++- src/network/access/qnetworkreplyhttpimpl.cpp | 13 ++++++++++--- src/network/access/qnetworkreplyhttpimpl_p.h | 4 ++-- src/network/access/qnetworkrequest.cpp | 7 +++++++ src/network/access/qnetworkrequest.h | 1 + 8 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 24ada3a81f4..612abb90441 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -299,6 +299,11 @@ void QHttpNetworkReply::setSpdyWasUsed(bool spdy) d_func()->spdyUsed = spdy; } +qint64 QHttpNetworkReply::removedContentLength() const +{ + return d_func()->removedContentLength; +} + bool QHttpNetworkReply::isRedirecting() const { return d_func()->isRedirecting(); @@ -326,6 +331,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) currentlyReceivedDataInWindow(0), currentlyUploadedDataInWindow(0), totallyUploadedData(0), + removedContentLength(-1), connection(0), autoDecompress(false), responseData(), requestIsPrepared(false) ,pipeliningUsed(false), spdyUsed(false), downstreamLimited(false) @@ -398,12 +404,12 @@ void QHttpNetworkReplyPrivate::removeAutoDecompressHeader() end = fields.end(); while (it != end) { if (qstricmp(name.constData(), it->first.constData()) == 0) { + removedContentLength = strtoull(it->second.constData(), nullptr, 0); fields.erase(it); break; } ++it; } - } bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index f3b007f594f..faab03f0568 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -139,6 +139,7 @@ public: bool isPipeliningUsed() const; bool isSpdyUsed() const; void setSpdyWasUsed(bool spdy); + qint64 removedContentLength() const; bool isRedirecting() const; @@ -255,6 +256,7 @@ public: qint32 currentlyReceivedDataInWindow; // only for SPDY qint32 currentlyUploadedDataInWindow; // only for SPDY qint64 totallyUploadedData; // only for SPDY + qint64 removedContentLength; QPointer connection; QPointer connectionChannel; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 1dca7f02fb6..e71911cec2f 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -234,6 +234,7 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) : , isPipeliningUsed(false) , isSpdyUsed(false) , incomingContentLength(-1) + , removedContentLength(-1) , incomingErrorCode(QNetworkReply::NoError) , downloadBuffer() , httpConnection(0) @@ -623,6 +624,7 @@ void QHttpThreadDelegate::headerChangedSlot() incomingReasonPhrase = httpReply->reasonPhrase(); isPipeliningUsed = httpReply->isPipeliningUsed(); incomingContentLength = httpReply->contentLength(); + removedContentLength = httpReply->removedContentLength(); isSpdyUsed = httpReply->isSpdyUsed(); emit downloadMetaData(incomingHeaders, @@ -631,6 +633,7 @@ void QHttpThreadDelegate::headerChangedSlot() isPipeliningUsed, downloadBuffer, incomingContentLength, + removedContentLength, isSpdyUsed); } diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h index 64c58cf6488..6d1ea11f293 100644 --- a/src/network/access/qhttpthreaddelegate_p.h +++ b/src/network/access/qhttpthreaddelegate_p.h @@ -112,6 +112,7 @@ public: bool isPipeliningUsed; bool isSpdyUsed; qint64 incomingContentLength; + qint64 removedContentLength; QNetworkReply::NetworkError incomingErrorCode; QString incomingErrorDetail; #ifndef QT_NO_BEARERMANAGEMENT @@ -141,7 +142,7 @@ signals: void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *); #endif void downloadMetaData(const QList > &, int, const QString &, bool, - QSharedPointer, qint64, bool); + QSharedPointer, qint64, qint64, bool); void downloadProgress(qint64, qint64); void downloadData(const QByteArray &); void error(QNetworkReply::NetworkError, const QString &); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index b5e44fa29aa..f70f11d3840 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -805,10 +805,11 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq Qt::QueuedConnection); QObject::connect(delegate, SIGNAL(downloadMetaData(QList >, int, QString, bool, - QSharedPointer, qint64, bool)), + QSharedPointer, qint64, qint64, + bool)), q, SLOT(replyDownloadMetaData(QList >, int, QString, bool, - QSharedPointer, qint64, bool)), + QSharedPointer, qint64, qint64, bool)), Qt::QueuedConnection); QObject::connect(delegate, SIGNAL(downloadProgress(qint64,qint64)), q, SLOT(replyDownloadProgressSlot(qint64,qint64)), @@ -913,6 +914,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq delegate->isPipeliningUsed, QSharedPointer(), delegate->incomingContentLength, + delegate->removedContentLength, delegate->isSpdyUsed); replyDownloadData(delegate->synchronousDownloadData); httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail); @@ -924,6 +926,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq delegate->isPipeliningUsed, QSharedPointer(), delegate->incomingContentLength, + delegate->removedContentLength, delegate->isSpdyUsed); replyDownloadData(delegate->synchronousDownloadData); } @@ -1151,7 +1154,9 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode) void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList > &hm, int sc, const QString &rp, bool pu, QSharedPointer db, - qint64 contentLength, bool spdyWasUsed) + qint64 contentLength, + qint64 removedContentLength, + bool spdyWasUsed) { Q_Q(QNetworkReplyHttpImpl); Q_UNUSED(contentLength); @@ -1197,6 +1202,8 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QListsetAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode); q->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase); + if (removedContentLength != -1) + q->setAttribute(QNetworkRequest::OriginalContentLengthAttribute, removedContentLength); // is it a redirection? if (!isHttpRedirectResponse()) diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index 868fa617b6e..255c23006e5 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -114,7 +114,7 @@ public: Q_PRIVATE_SLOT(d_func(), void replyFinished()) Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList >, int, QString, bool, QSharedPointer, - qint64, bool)) + qint64, qint64, bool)) Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64)) Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *)) Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &)) @@ -280,7 +280,7 @@ public: void replyDownloadData(QByteArray); void replyFinished(); void replyDownloadMetaData(const QList > &, int, const QString &, - bool, QSharedPointer, qint64, bool); + bool, QSharedPointer, qint64, qint64, bool); void replyDownloadProgressSlot(qint64,qint64); void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpError(QNetworkReply::NetworkError error, const QString &errorString); diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 29362b81e26..bc2507ca51c 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -282,6 +282,13 @@ QT_BEGIN_NAMESPACE that is redirecting from "https" to "http" protocol, are not allowed. (This value was introduced in 5.6.) + \value OriginalContentLengthAttribute + Replies only, type QMetaType::Int + Holds the original content-length attribute before being invalidated and + removed from the header when the data is compressed and the request was + marked to be decompressed automatically. + (This value was introduced in 5.9.) + \value User Special type. Additional information can be passed in QVariants with types ranging from User to UserMax. The default diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 00375f285c9..b8bcdc4bfb8 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -91,6 +91,7 @@ public: HTTP2WasUsedAttribute, EmitAllUploadProgressSignalsAttribute, FollowRedirectsAttribute, + OriginalContentLengthAttribute, User = 1000, UserMax = 32767