303QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(
const QUrl &newUrl)
304 : QHttpNetworkHeaderPrivate(newUrl)
305 , state(NothingDoneState)
307 bodyLength(0), contentRead(0), totalProgress(0),
308 chunkedTransferEncoding(
false),
309 connectionCloseEnabled(
true),
310 forceConnectionCloseEnabled(
false),
311 lastChunkRead(
false),
312 currentChunkSize(0), currentChunkRead(0), readBufferMaxSize(0),
313 totallyUploadedData(0),
314 removedContentLength(-1),
316 autoDecompress(
false), responseData(), requestIsPrepared(
false)
317 ,pipeliningUsed(
false), h2Used(
false), downstreamLimited(
false)
318 ,userProvidedDownloadBuffer(
nullptr)
321 QString scheme = newUrl.scheme();
322 if (scheme ==
"preconnect-http"_L1 || scheme ==
"preconnect-https"_L1)
324 connectionCloseEnabled =
false;
368void QHttpNetworkReplyPrivate::removeAutoDecompressHeader()
372 constexpr auto name = QByteArrayView(
"content-length");
373 QByteArray contentLength = parser.firstHeaderField(name);
374 bool parseOk =
false;
375 qint64 value = contentLength.toLongLong(&parseOk);
377 removedContentLength = value;
378 parser.removeHeaderField(name);
382qint64 QHttpNetworkReplyPrivate::readStatus(QIODevice *socket)
384 if (fragment.isEmpty()) {
386 fragment.reserve(32);
394 haveRead = socket->read(&c, 1);
397 else if (haveRead == 0)
399 else if (haveRead == 1 && fragment.size() == 0 && (c == 11 || c ==
'\n' || c ==
'\r' || c ==
' ' || c == 31))
407 if (fragment.endsWith(
'\r')) {
408 fragment.truncate(fragment.size()-1);
410 bool ok = parseStatus(fragment);
411 state = ReadingHeaderState;
422 if (fragment.size() == 5 && !fragment.startsWith(
"HTTP/")) {
426 }
while (haveRead == 1);
436qint64 QHttpNetworkReplyPrivate::readHeader(QIODevice *socket)
438 if (fragment.isEmpty()) {
442 fragment.reserve(512);
447 bool allHeaders =
false;
450 haveRead = socket->read(&c, 1);
454 }
else if (haveRead == -1) {
465 if (fragment.endsWith(
"\n\r\n")
466 || fragment.endsWith(
"\n\n"))
470 if ((fragment.size() == 2 && fragment.endsWith(
"\r\n"))
471 || (fragment.size() == 1 && fragment.endsWith(
"\n")))
475 }
while (!allHeaders && haveRead > 0);
479 parseHeader(fragment);
480 state = ReadingDataState;
482 bodyLength = contentLength();
485 chunkedTransferEncoding = headerField(
"transfer-encoding").toLower().contains(
"chunked");
488 QByteArray connectionHeaderField = headerField(
"connection");
490 connectionCloseEnabled = (connectionHeaderField.toLower().contains(
"close") ||
491 headerField(
"proxy-connection").toLower().contains(
"close")) ||
492 (parser.getMajorVersion() == 1 && parser.getMinorVersion() == 0 &&
493 (connectionHeaderField.isEmpty() && !headerField(
"proxy-connection").toLower().contains(
"keep-alive")));
539qint64 QHttpNetworkReplyPrivate::readBodyFast(QIODevice *socket, QByteDataBuffer *rb)
542 qint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead);
543 if (readBufferMaxSize)
544 toBeRead = qMin(toBeRead, readBufferMaxSize);
551 qint64 haveRead = socket->read(bd.data(), toBeRead);
552 if (haveRead == -1) {
560 if (contentRead + haveRead == bodyLength) {
561 state = AllDoneState;
564 contentRead += haveRead;
569qint64 QHttpNetworkReplyPrivate::readBody(QIODevice *socket, QByteDataBuffer *out)
575 bytes += readReplyBodyChunked(socket, out);
576 }
else if (bodyLength > 0) {
578 bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead);
579 if (contentRead + bytes == bodyLength)
580 state = AllDoneState;
583 bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable());
585 contentRead += bytes;
589qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *socket, QByteDataBuffer *out, qint64 size)
596 int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable()));
598 if (readBufferMaxSize)
599 toBeRead = qMin<qint64>(toBeRead, readBufferMaxSize);
601 while (toBeRead > 0) {
603 byteData.resize(toBeRead);
604 qint64 haveRead = socket->read(byteData.data(), byteData.size());
611 byteData.resize(haveRead);
612 out->append(byteData);
616 toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable()));
622qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *socket, QByteDataBuffer *out)
625 while (socket->bytesAvailable()) {
627 if (readBufferMaxSize && (bytes > readBufferMaxSize))
630 if (!lastChunkRead && currentChunkRead >= currentChunkSize) {
632 currentChunkSize = 0;
633 currentChunkRead = 0;
638 qint64 haveRead = socket->read(crlf, 2);
648 bytes += getChunkSize(socket, ¤tChunkSize);
649 if (currentChunkSize == -1)
653 if (currentChunkSize == 0 || lastChunkRead) {
654 lastChunkRead =
true;
657 qint64 haveRead = socket->read(crlf, 2);
661 if ((haveRead == 2 && crlf[0] ==
'\r' && crlf[1] ==
'\n') || (haveRead == 1 && crlf[0] ==
'\n'))
662 state = AllDoneState;
663 else if (haveRead == 1 && crlf[0] ==
'\r')
665 else if (haveRead > 0) {
667 forceConnectionCloseEnabled =
true;
668 state = AllDoneState;
674 qint64 haveRead = readReplyBodyRaw (socket, out, currentChunkSize - currentChunkRead);
675 currentChunkRead += haveRead;
684qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *socket, qint64 *chunkSize)
690 int bytesAvailable = socket->bytesAvailable();
692 while (bytesAvailable > bytes) {
693 qint64 sniffedBytes = socket->peek(crlf, 2);
694 int fragmentSize = fragment.size();
697 if ((fragmentSize && sniffedBytes == 2 && crlf[0] ==
'\r' && crlf[1] ==
'\n')
698 ||(fragmentSize > 1 && fragment.endsWith(
'\r') && crlf[0] ==
'\n'))
700 bytes += socket->read(crlf, 1);
702 bytes += socket->read(crlf, 1);
705 const auto fragmentView = QByteArrayView(fragment).mid(0, fragment.indexOf(
';')).trimmed();
706 *chunkSize = fragmentView.toLong(&ok, 16);
712 qint64 haveRead = socket->read(&c, 1);
739bool QHttpNetworkReplyPrivate::expectContent()
741 int statusCode = parser.getStatusCode();
743 if ((statusCode >= 100 && statusCode < 200)
744 || statusCode == 204 || statusCode == 304)
746 if (request.operation() == QHttpNetworkRequest::Head)
748 qint64 expectedContentLength = contentLength();
749 if (expectedContentLength == 0)
751 if (expectedContentLength == -1 && bodyLength == 0) {