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 <edward.welbourne@qt.io>
This commit is contained in:
Jesus Fernandez 2016-04-13 17:00:48 +02:00 committed by Jesus Fernandez
parent 511623b6f0
commit 7f14ad08bb
8 changed files with 34 additions and 7 deletions

View File

@ -299,6 +299,11 @@ void QHttpNetworkReply::setSpdyWasUsed(bool spdy)
d_func()->spdyUsed = spdy; d_func()->spdyUsed = spdy;
} }
qint64 QHttpNetworkReply::removedContentLength() const
{
return d_func()->removedContentLength;
}
bool QHttpNetworkReply::isRedirecting() const bool QHttpNetworkReply::isRedirecting() const
{ {
return d_func()->isRedirecting(); return d_func()->isRedirecting();
@ -326,6 +331,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
currentlyReceivedDataInWindow(0), currentlyReceivedDataInWindow(0),
currentlyUploadedDataInWindow(0), currentlyUploadedDataInWindow(0),
totallyUploadedData(0), totallyUploadedData(0),
removedContentLength(-1),
connection(0), connection(0),
autoDecompress(false), responseData(), requestIsPrepared(false) autoDecompress(false), responseData(), requestIsPrepared(false)
,pipeliningUsed(false), spdyUsed(false), downstreamLimited(false) ,pipeliningUsed(false), spdyUsed(false), downstreamLimited(false)
@ -398,12 +404,12 @@ void QHttpNetworkReplyPrivate::removeAutoDecompressHeader()
end = fields.end(); end = fields.end();
while (it != end) { while (it != end) {
if (qstricmp(name.constData(), it->first.constData()) == 0) { if (qstricmp(name.constData(), it->first.constData()) == 0) {
removedContentLength = strtoull(it->second.constData(), nullptr, 0);
fields.erase(it); fields.erase(it);
break; break;
} }
++it; ++it;
} }
} }
bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const

View File

@ -139,6 +139,7 @@ public:
bool isPipeliningUsed() const; bool isPipeliningUsed() const;
bool isSpdyUsed() const; bool isSpdyUsed() const;
void setSpdyWasUsed(bool spdy); void setSpdyWasUsed(bool spdy);
qint64 removedContentLength() const;
bool isRedirecting() const; bool isRedirecting() const;
@ -255,6 +256,7 @@ public:
qint32 currentlyReceivedDataInWindow; // only for SPDY qint32 currentlyReceivedDataInWindow; // only for SPDY
qint32 currentlyUploadedDataInWindow; // only for SPDY qint32 currentlyUploadedDataInWindow; // only for SPDY
qint64 totallyUploadedData; // only for SPDY qint64 totallyUploadedData; // only for SPDY
qint64 removedContentLength;
QPointer<QHttpNetworkConnection> connection; QPointer<QHttpNetworkConnection> connection;
QPointer<QHttpNetworkConnectionChannel> connectionChannel; QPointer<QHttpNetworkConnectionChannel> connectionChannel;

View File

@ -234,6 +234,7 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) :
, isPipeliningUsed(false) , isPipeliningUsed(false)
, isSpdyUsed(false) , isSpdyUsed(false)
, incomingContentLength(-1) , incomingContentLength(-1)
, removedContentLength(-1)
, incomingErrorCode(QNetworkReply::NoError) , incomingErrorCode(QNetworkReply::NoError)
, downloadBuffer() , downloadBuffer()
, httpConnection(0) , httpConnection(0)
@ -623,6 +624,7 @@ void QHttpThreadDelegate::headerChangedSlot()
incomingReasonPhrase = httpReply->reasonPhrase(); incomingReasonPhrase = httpReply->reasonPhrase();
isPipeliningUsed = httpReply->isPipeliningUsed(); isPipeliningUsed = httpReply->isPipeliningUsed();
incomingContentLength = httpReply->contentLength(); incomingContentLength = httpReply->contentLength();
removedContentLength = httpReply->removedContentLength();
isSpdyUsed = httpReply->isSpdyUsed(); isSpdyUsed = httpReply->isSpdyUsed();
emit downloadMetaData(incomingHeaders, emit downloadMetaData(incomingHeaders,
@ -631,6 +633,7 @@ void QHttpThreadDelegate::headerChangedSlot()
isPipeliningUsed, isPipeliningUsed,
downloadBuffer, downloadBuffer,
incomingContentLength, incomingContentLength,
removedContentLength,
isSpdyUsed); isSpdyUsed);
} }

View File

@ -112,6 +112,7 @@ public:
bool isPipeliningUsed; bool isPipeliningUsed;
bool isSpdyUsed; bool isSpdyUsed;
qint64 incomingContentLength; qint64 incomingContentLength;
qint64 removedContentLength;
QNetworkReply::NetworkError incomingErrorCode; QNetworkReply::NetworkError incomingErrorCode;
QString incomingErrorDetail; QString incomingErrorDetail;
#ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_BEARERMANAGEMENT
@ -141,7 +142,7 @@ signals:
void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *); void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *);
#endif #endif
void downloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, bool, void downloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, bool,
QSharedPointer<char>, qint64, bool); QSharedPointer<char>, qint64, qint64, bool);
void downloadProgress(qint64, qint64); void downloadProgress(qint64, qint64);
void downloadData(const QByteArray &); void downloadData(const QByteArray &);
void error(QNetworkReply::NetworkError, const QString &); void error(QNetworkReply::NetworkError, const QString &);

View File

@ -805,10 +805,11 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
Qt::QueuedConnection); Qt::QueuedConnection);
QObject::connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >, QObject::connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool, int, QString, bool,
QSharedPointer<char>, qint64, bool)), QSharedPointer<char>, qint64, qint64,
bool)),
q, SLOT(replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >, q, SLOT(replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool, int, QString, bool,
QSharedPointer<char>, qint64, bool)), QSharedPointer<char>, qint64, qint64, bool)),
Qt::QueuedConnection); Qt::QueuedConnection);
QObject::connect(delegate, SIGNAL(downloadProgress(qint64,qint64)), QObject::connect(delegate, SIGNAL(downloadProgress(qint64,qint64)),
q, SLOT(replyDownloadProgressSlot(qint64,qint64)), q, SLOT(replyDownloadProgressSlot(qint64,qint64)),
@ -913,6 +914,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
delegate->isPipeliningUsed, delegate->isPipeliningUsed,
QSharedPointer<char>(), QSharedPointer<char>(),
delegate->incomingContentLength, delegate->incomingContentLength,
delegate->removedContentLength,
delegate->isSpdyUsed); delegate->isSpdyUsed);
replyDownloadData(delegate->synchronousDownloadData); replyDownloadData(delegate->synchronousDownloadData);
httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail); httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail);
@ -924,6 +926,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
delegate->isPipeliningUsed, delegate->isPipeliningUsed,
QSharedPointer<char>(), QSharedPointer<char>(),
delegate->incomingContentLength, delegate->incomingContentLength,
delegate->removedContentLength,
delegate->isSpdyUsed); delegate->isSpdyUsed);
replyDownloadData(delegate->synchronousDownloadData); replyDownloadData(delegate->synchronousDownloadData);
} }
@ -1151,7 +1154,9 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode)
void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &hm, void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &hm,
int sc, const QString &rp, bool pu, int sc, const QString &rp, bool pu,
QSharedPointer<char> db, QSharedPointer<char> db,
qint64 contentLength, bool spdyWasUsed) qint64 contentLength,
qint64 removedContentLength,
bool spdyWasUsed)
{ {
Q_Q(QNetworkReplyHttpImpl); Q_Q(QNetworkReplyHttpImpl);
Q_UNUSED(contentLength); Q_UNUSED(contentLength);
@ -1197,6 +1202,8 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte
q->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode); q->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
q->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase); q->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase);
if (removedContentLength != -1)
q->setAttribute(QNetworkRequest::OriginalContentLengthAttribute, removedContentLength);
// is it a redirection? // is it a redirection?
if (!isHttpRedirectResponse()) if (!isHttpRedirectResponse())

View File

@ -114,7 +114,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void replyFinished()) Q_PRIVATE_SLOT(d_func(), void replyFinished())
Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >, Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool, QSharedPointer<char>, int, QString, bool, QSharedPointer<char>,
qint64, bool)) qint64, qint64, bool))
Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64)) 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 httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *))
Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &)) Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &))
@ -280,7 +280,7 @@ public:
void replyDownloadData(QByteArray); void replyDownloadData(QByteArray);
void replyFinished(); void replyFinished();
void replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, void replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &,
bool, QSharedPointer<char>, qint64, bool); bool, QSharedPointer<char>, qint64, qint64, bool);
void replyDownloadProgressSlot(qint64,qint64); void replyDownloadProgressSlot(qint64,qint64);
void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
void httpError(QNetworkReply::NetworkError error, const QString &errorString); void httpError(QNetworkReply::NetworkError error, const QString &errorString);

View File

@ -282,6 +282,13 @@ QT_BEGIN_NAMESPACE
that is redirecting from "https" to "http" protocol, are not allowed. that is redirecting from "https" to "http" protocol, are not allowed.
(This value was introduced in 5.6.) (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 \value User
Special type. Additional information can be passed in Special type. Additional information can be passed in
QVariants with types ranging from User to UserMax. The default QVariants with types ranging from User to UserMax. The default

View File

@ -91,6 +91,7 @@ public:
HTTP2WasUsedAttribute, HTTP2WasUsedAttribute,
EmitAllUploadProgressSignalsAttribute, EmitAllUploadProgressSignalsAttribute,
FollowRedirectsAttribute, FollowRedirectsAttribute,
OriginalContentLengthAttribute,
User = 1000, User = 1000,
UserMax = 32767 UserMax = 32767