Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-116476

Explicitly opening QNetworkRequest causes bytes available to be erased.

    XMLWordPrintable

Details

    Description

      QNetworkAccessManager opens QNetworkRequest for you so you don't need to call QNetworkRequest::open() explicitly, yes. But doing so shouldn't cause data loss I believe.

      Data loss did not happen to old Qt versions, e.g. 5.7, nor new versions, e.g. 6.5. But 5.15 suffers such issue. A simple reproducer is below. Give it an URL as argument, e.g. https://qt.io, and run it.

      #include <QCoreApplication>
      #include <QEventLoop>
      #include <QNetworkAccessManager>
      #include <QNetworkReply>
      #include <QNetworkRequest>
      #include <QUrl>
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          QString urlString = a.arguments().value(1);
          QUrl url(urlString);
          if (urlString.isEmpty() || !url.isValid())
          {
              qCritical("Syntax:");
              qCritical("    %s <URL>", qPrintable(a.applicationName()));
              return 1;
          }
      
          QNetworkAccessManager manager;
          QNetworkRequest request(url);
          QNetworkReply* reply = manager.get(request);
          QEventLoop eventLoop;
          QObject::connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
          QObject::connect(reply, &QNetworkReply::errorOccurred, &eventLoop, &QEventLoop::quit);
          QObject::connect(reply, &QNetworkReply::sslErrors, [=](const QList<QSslError>& e) { reply->ignoreSslErrors(e); });
          QObject::connect(reply, &QNetworkReply::downloadProgress, [=](qint64 r, qint64 t) { qInfo("%lld/%lld", r, t); });
          eventLoop.exec();
      
          if (reply->error() != QNetworkReply::NetworkError::NoError)
          {
              qWarning("Error Occurred: %s", qPrintable(reply->errorString()));
              return 1;
          }
      
          QString urlDisplayString = url.toString(QUrl::UrlFormattingOption::RemoveQuery);
          if (url.hasQuery())
          {
              urlDisplayString.append("?<REDACTED>");
          }
          qInfo("Reply Received from %s", qPrintable(urlDisplayString));
          qInfo("Bytes Available: %lld", reply->bytesAvailable());
      
          QByteArray body;
          if (reply->open(QIODevice::ReadOnly))
          {
              qInfo("Reply opened. Bytes available is %d now", reply->bytesAvailable());
              body = reply->readAll();
          }
      
          if (body.isEmpty())
          {
              qWarning("Response Body is Empty");
          }
          else
          {
              qInfo("Response Body Length: %d", body.length());
          }
      
          return 0;
      }
      

      Notice how reply->bytesAvailable() returns 298 (in case of Qt website) at the first place but 0 after reply->open(QIODevice::ReadOnly). Then nothing can be read.

      Problem is gone if reply->readAll() is called without opening. But as aforementioned, I think opening it again should not cause any harm.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            manordheim MÃ¥rten Nordheim
            luqiaochen Luqiao Chen
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes