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/")) {
430 if (fragment.size() > HeaderConstants::MAX_REASON_PHRASE_SIZE + 64) {
434 }
while (haveRead == 1);
444qint64 QHttpNetworkReplyPrivate::readHeader(QIODevice *socket)
446 if (fragment.isEmpty()) {
450 fragment.reserve(512);
455 bool allHeaders =
false;
458 haveRead = socket->read(&c, 1);
462 }
else if (haveRead == -1) {
470 if (fragment.size() > parser.maxRawHeaderSize()) {
479 if (fragment.endsWith(
"\n\r\n")
480 || fragment.endsWith(
"\n\n"))
484 if ((fragment.size() == 2 && fragment.endsWith(
"\r\n"))
485 || (fragment.size() == 1 && fragment.endsWith(
"\n")))
489 }
while (!allHeaders && haveRead > 0);
493 parseHeader(fragment);
494 state = ReadingDataState;
496 bodyLength = contentLength();
499 chunkedTransferEncoding = headerField(
"transfer-encoding").toLower().contains(
"chunked");
502 QByteArray connectionHeaderField = headerField(
"connection");
504 connectionCloseEnabled = (connectionHeaderField.toLower().contains(
"close") ||
505 headerField(
"proxy-connection").toLower().contains(
"close")) ||
506 (parser.getMajorVersion() == 1 && parser.getMinorVersion() == 0 &&
507 (connectionHeaderField.isEmpty() && !headerField(
"proxy-connection").toLower().contains(
"keep-alive")));
553qint64 QHttpNetworkReplyPrivate::readBodyFast(QIODevice *socket, QByteDataBuffer *rb)
556 qint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead);
557 if (readBufferMaxSize)
558 toBeRead = qMin(toBeRead, readBufferMaxSize);
565 qint64 haveRead = socket->read(bd.data(), toBeRead);
566 if (haveRead == -1) {
574 if (contentRead + haveRead == bodyLength) {
575 state = AllDoneState;
578 contentRead += haveRead;
583qint64 QHttpNetworkReplyPrivate::readBody(QIODevice *socket, QByteDataBuffer *out)
589 bytes += readReplyBodyChunked(socket, out);
590 }
else if (bodyLength > 0) {
592 bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead);
593 if (contentRead + bytes == bodyLength)
594 state = AllDoneState;
597 bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable());
599 contentRead += bytes;
603qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *socket, QByteDataBuffer *out, qint64 size)
610 int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable()));
612 if (readBufferMaxSize)
613 toBeRead = qMin<qint64>(toBeRead, readBufferMaxSize);
615 while (toBeRead > 0) {
617 byteData.resize(toBeRead);
618 qint64 haveRead = socket->read(byteData.data(), byteData.size());
625 byteData.resize(haveRead);
626 out->append(byteData);
630 toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable()));
636qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *socket, QByteDataBuffer *out)
639 while (socket->bytesAvailable()) {
641 if (readBufferMaxSize && (bytes > readBufferMaxSize))
644 if (!lastChunkRead && currentChunkRead >= currentChunkSize) {
646 currentChunkSize = 0;
647 currentChunkRead = 0;
652 qint64 haveRead = socket->read(crlf, 2);
662 bytes += getChunkSize(socket, ¤tChunkSize);
663 if (currentChunkSize == -1)
667 if (currentChunkSize == 0 || lastChunkRead) {
668 lastChunkRead =
true;
671 qint64 haveRead = socket->read(crlf, 2);
675 if ((haveRead == 2 && crlf[0] ==
'\r' && crlf[1] ==
'\n') || (haveRead == 1 && crlf[0] ==
'\n'))
676 state = AllDoneState;
677 else if (haveRead == 1 && crlf[0] ==
'\r')
679 else if (haveRead > 0) {
681 forceConnectionCloseEnabled =
true;
682 state = AllDoneState;
688 qint64 haveRead = readReplyBodyRaw (socket, out, currentChunkSize - currentChunkRead);
689 currentChunkRead += haveRead;
698qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *socket, qint64 *chunkSize)
704 int bytesAvailable = socket->bytesAvailable();
706 while (bytesAvailable > bytes) {
707 qint64 sniffedBytes = socket->peek(crlf, 2);
708 int fragmentSize = fragment.size();
711 if ((fragmentSize && sniffedBytes == 2 && crlf[0] ==
'\r' && crlf[1] ==
'\n')
712 ||(fragmentSize > 1 && fragment.endsWith(
'\r') && crlf[0] ==
'\n'))
714 bytes += socket->read(crlf, 1);
716 bytes += socket->read(crlf, 1);
719 const auto fragmentView = QByteArrayView(fragment).mid(0, fragment.indexOf(
';')).trimmed();
720 *chunkSize = fragmentView.toLong(&ok, 16);
726 qint64 haveRead = socket->read(&c, 1);
753bool QHttpNetworkReplyPrivate::expectContent()
755 int statusCode = parser.getStatusCode();
757 if ((statusCode >= 100 && statusCode < 200)
758 || statusCode == 204 || statusCode == 304)
760 if (request.operation() == QHttpNetworkRequest::Head)
762 qint64 expectedContentLength = contentLength();
763 if (expectedContentLength == 0)
765 if (expectedContentLength == -1 && bodyLength == 0) {