QNetworkReply readAll() gets empty data on finished()



  • Hi guys,

    i am quite furious about my problem and don't know how to solve it. I need to send GET request to some site and receive responce. All i get is empty string.

    I have my MainWindow app, which has as member QNetworkAccessManager

    Header:
    @class MainWindow : public QMainWindow, public Ui::mainWindow
    {
    Q_OBJECT

    private:
    QNetworkAccessManager m_netAccessManager;
    QNetworkReply * reply;

    public:
    MainWindow( QWidget * parent = 0 );
    ~MainWindow();

    private slots:
    void httpFinished();

    // menu slots
    void update();
    

    };@

    Source:
    @void MainWindow::updateFonds()
    {
    QUrl url = QString::fromLocal8Bit("http://www.qt-project.org");
    QNetworkRequest request(url);

    reply = m_netAccessManager.get( request );
    
    QObject::connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
    

    };

    void MainWindow::httpFinished()
    {
    // check for error
    if ( reply->error() )
    {
    QString form("Download of %1 failed: %2\n");
    this->statusbar->showMessage( form.arg(reply->url().toEncoded().constData()).arg(qPrintable(reply->errorString())) );
    } else {
    // get http response code
    QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    QVariant contentLengthV = reply->header(QNetworkRequest::ContentLengthHeader);
    QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);

        if ( statusCodeV.toInt() == 302 )
        {
            reply->deleteLater();
            reply = nullptr;
    
            QNetworkRequest request( redirectionTargetUrl.toUrl() );
            reply = m_netAccessManager.get(request);
            connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
            return;
        }
    
        qDebug() << statusCodeV.toString();
        qDebug() << contentLengthV.toString();
        qDebug() << reply->readAll();
    }
    
    reply->deleteLater();
    reply = NULL;
    

    };@

    All i get is empty string. Tried wireshark to check if i am receiving response and i am. If i try to catch readyRead() signal i can read a chunk of response but i don't want to do it this way.

    In help it says:

    bq. if no calls to read() were made as a result of readyRead(), a call to readAll() will retrieve the full contents in a QByteArray.

    But it doesnt apply:( Can u help me?



  • Hi,

    Check out the note in the NetworkError "documentation":http://doc.qt.io/qt-5/qnetworkreply.html#NetworkError-enum. Maybe the qt-project site or the site you are accessing requires a redirect.

    By the way, QNetworkAccessManager::get() creates a new QNetworkReply object on the heap each time you call it. Don't forget to call deleteLater() on QNetworkReply in the slot connected to finished() and set the pointer to null.



  • Hi, thx for reply but this is not the case.

    I know, i omitted deleting (leads only to memory leaking) and i am sure there is no redirecting (since i did a check by wireshark) but ok, i updated my code.

    Result is still the same:

    @"200"
    "180900"
    ""@


  • Moderators

    Hi,

    You need to connect to QNAM's "finished()":http://doc.qt.io/qt-5/qnetworkaccessmanager.html#finished signal and not to the QNetworkReply's signal.



  • Ok, fine.

    But - use either QNetworkReply that is return value from get() function or the one from QNAM's finish slot?


  • Moderators

    QNAM’s finish slot.



  • Ok, must say i did tried it before, but ok. (as documentation says it is emitted in tandem so it doesn't matter if i use finish() on saved QNetworkReplay or QNetworkAccessManager).

    Same result - code now looks like this.

    Header:

    @class MainWindow : public QMainWindow, public Ui::mainWindow
    {
    Q_OBJECT

    private:
    QNetworkAccessManager m_netAccessManager;

    public:
    MainWindow( QWidget * parent = 0 );
    ~MainWindow();

    private slots:
    void httpFinished( QNetworkReply * httpReply );

    // menu slots
    void updateFonds();
    

    };@

    Source:

    @MainWindow::MainWindow( QWidget * parent )
    : QMainWindow( parent )
    {
    setupUi(this);
    connect( &m_netAccessManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(httpFinished( QNetworkReply *) ) );
    };

    MainWindow::~MainWindow()
    {};

    void MainWindow::httpFinished( QNetworkReply * httpReply )
    {
    // check for error
    if ( httpReply->error() )
    {
    QString form("Download of %1 failed: %2\n");
    this->statusbar->showMessage( form.arg(httpReply->url().toEncoded().constData()).arg(qPrintable(httpReply->errorString())) );
    } else {
    // get http response code
    QVariant statusCodeV = httpReply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    QVariant contentLengthV = httpReply->header(QNetworkRequest::ContentLengthHeader);
    QVariant redirectionTargetUrl = httpReply->attribute(QNetworkRequest::RedirectionTargetAttribute);

        if ( statusCodeV.toInt() == 302 )
        {
            QNetworkRequest request( redirectionTargetUrl.toUrl() );
            m_netAccessManager.get(request);
    
            httpReply->deleteLater();
            return;
        }
    
        qDebug() << statusCodeV.toString();
        qDebug() << contentLengthV.toString();
        qDebug() << httpReply->readAll();
    }
    
    httpReply->deleteLater();
    

    };

    void MainWindow::updateFonds()
    {
    QUrl url = QString::fromLocal8Bit("http://www.qt-project.org");
    QNetworkRequest request(url);

    reply = m_netAccessManager.get( request );
    

    };@


  • Moderators

    You might be getting a redirection, to check it, check if redirectionTargetUrl is not null. Remove if ( statusCodeV.toInt() == 302 ).
    Try following:
    @
    qDebug() << httpReply->readAll() //This will provide some useful info.

    QVariant redirectionTargetUrl = httpReply->attribute(QNetworkRequest::RedirectionTargetAttribute);

    if(!redirectionTargetUrl!=null) {
    QUrl newUrl = QUrl(redirectionTargetUrl.toUrl());
    QNetworkRequest request(newUrl);
    reply = m_netAccessManager..get(request);
    }
    @



  • Hm..ok, so be it (server can send wrong HTTP response code).

    @void MainWindow::httpFinished( QNetworkReply * httpReply )
    {
    // check for error
    if ( httpReply->error() )
    {
    QString form("Download of %1 failed: %2\n");
    this->statusbar->showMessage( form.arg(httpReply->url().toEncoded().constData()).arg(qPrintable(httpReply->errorString())) );
    } else {
    QVariant contentLengthV = httpReply->header(QNetworkRequest::ContentLengthHeader);
    QVariant statusCodeV = httpReply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    qDebug() << statusCodeV.toString();
    qDebug() << httpReply->readAll();
    qDebug() << contentLengthV.toString();

        QVariant redirectionTargetUrl = httpReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
    
        if ( !redirectionTargetUrl.isNull() )
        {
            QNetworkRequest request( redirectionTargetUrl.toUrl() );
            m_netAccessManager.get(request);
    
            httpReply->deleteLater();
            return;
        }
    }
    
    httpReply->deleteLater();
    

    };@

    And i still get (HTTP CODE, and LENGTH)
    @"200"
    "180900"@


  • Moderators

    Well I'm not sure about the problem now. The following code works for me. Try it,
    @
    ui(new Ui::Dialog), m_qnam()
    {
    ui->setupUi(this);
    connect(&m_qnam,SIGNAL(finished(QNetworkReply*)),
    this,SLOT(onFinished(QNetworkReply*)));

    QUrl url = QString::fromLocal8Bit("http://www.qt-project.org");
    QNetworkRequest request(url);
    m_qnam.get(request);
    

    }

    void Dialog::onFinished(QNetworkReply* reply)
    {
    QVariant redirectionTarget =
    reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
    qDebug() << redirectionTarget;
    if (!redirectionTarget.isNull()) {
    QUrl newUrl = QUrl(redirectionTarget.toUrl());
    QNetworkRequest request(newUrl);
    m_qnam.get(request);
    } else {
    qDebug() << reply->readAll();
    }
    reply->deleteLater();
    }
    @



  • Can u pls post whole code? (header including)


  • Moderators

    Sure its the default template for Qt Widgets Aplication with Dialog as base class. Here's the header
    @
    #ifndef DIALOG_H
    #define DIALOG_H

    #include <QDialog>
    #include <QNetworkAccessManager>
    #include <QNetworkReply>

    namespace Ui {
    class Dialog;
    }

    class Dialog : public QDialog
    {
    Q_OBJECT

    public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

    public slots:
    void onFinished(QNetworkReply *reply);

    private:
    Ui::Dialog *ui;
    QNetworkAccessManager m_qnam;
    };

    #endif // DIALOG_H
    @


  • Moderators

    And dialog.cpp
    @
    #include "dialog.h"
    #include "ui_dialog.h"

    #include <QNetworkRequest>

    Dialog::Dialog(QWidget parent) :
    QDialog(parent),
    ui(new Ui::Dialog), m_qnam()
    {
    ui->setupUi(this);
    connect(&m_qnam,SIGNAL(finished(QNetworkReply
    )),
    this,SLOT(onFinished(QNetworkReply*)));
    QUrl url = QString::fromLocal8Bit("http://www.qt-project.org");
    QNetworkRequest request(url);
    m_qnam.get(request);
    }

    Dialog::~Dialog()
    {
    delete ui;
    }

    void Dialog::onFinished(QNetworkReply* reply)
    {
    QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
    qDebug() << redirectionTarget;
    if (!redirectionTarget.isNull()) {
    QUrl newUrl = QUrl(redirectionTarget.toUrl());
    QNetworkRequest request(newUrl);
    m_qnam.get(request);
    } else {
    qDebug() << reply->readAll();
    }
    reply->deleteLater();
    }
    @



  • Result:

    @'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\bin\icuin53.dll', Binary was not built with debug information.
    'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\bin\icuuc53.dll', Binary was not built with debug information.
    'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\bin\icudt53.dll', Binary was not built with debug information.
    'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\bin\Qt5Widgetsd.dll', Symbols loaded.
    'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\bin\Qt5Guid.dll', Symbols loaded.
    'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\bin\Qt5Networkd.dll', Symbols loaded.
    'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\plugins\platforms\qwindowsd.dll', Symbols loaded.
    'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\plugins\bearer\qgenericbearerd.dll', Symbols loaded.
    'Sample.exe': Loaded 'D:\Dev\qt-prebuild\5.4\msvc2010_opengl\plugins\bearer\qnativewifibearerd.dll', Symbols loaded.
    QVariant(QUrl, QUrl("http://qt-project.org/") )
    The thread 'Win32 Thread' (0x1148) has exited with code 0 (0x0).
    QVariant(Invalid)
    @

    So, first time it is redirecting - ok, second time is requested url and no output....


  • Moderators

    Strange. Which Qt Version?
    Anyway, "here's":https://drive.google.com/file/d/0B3rkZH6q1E7oV2MwbkUzTVRrQlE/view?usp=sharing the complete project
    Download and check if it works as it is.



  • As original post (and tags) says:

    Qt 5.1.1 (msvc 2010 version without OGL) and Qt 5.4 (msvc 2010 version with OGL). Downloaded from online installer...

    Edit: ur code has same result..


  • Moderators

    That's weird. It works perfectly on my system, Ubuntu 14.04. Try removing reply->deleteLater() from onFinished(QNetworkReply* reply) slot.



  • Surely. I am not new to Qt even in programming.

    I tried even my own compiled versions and same result. I have also tried make it synchronous (after calling get, i entered into event loop and woke up when finished is emit).

    The only thing which works is catching readyRead signal and store chunks.

    For my perspective, something is reading that buffer before i get it on finish slot. Or closes it or idk...


  • Moderators

    But there's nothing in the code that I sent which would cause some abrupt buffer reading. I'm now running out if ideas.
    Surely someone other has a better explanation for this behaviour.



  • Is it possible, somehow, that the function in which the request is sent is called more than once? If this is the case, than when the slot is called, let's say, for the first QNetworkReply object, you access the second or third instance which has no data yet.

    Even if this is not the case, it is not a good idea to keep a member variable to the QNetworkReply object. Connecting the slot to the QNAM::finished(QNetworkReply*) signal is better because you know for sure from which QNetworkReply object to readAll().



  • Hi,

    didn't see you replied here. I am unable to fix it, even when storing link to QNetworkReply - and check whenever sender() is this reply.

    It seems that buffer is somehow read in inner slot, before emitting finish(). and it doesnt matter if it is emitted by QNR or QNAM.

    It seems not only me has same problem: "http://qt-project.org/forums/viewthread/51848/":http://qt-project.org/forums/viewthread/51848/

    Edit: it seems to have something to do with windows, not code. Maybe some point here?
    @'Sample.exe': Loaded 'C:\Windows\SysWOW64\WSHTCPIP.DLL', Cannot find or open the PDB file
    QVariant(Invalid)
    'Sample.exe': Unloaded 'C:\Windows\SysWOW64\WSHTCPIP.DLL'
    @



  • @Almer_Cz
    i meet the problem to with release version,
    but with debug version every this is ok.
    Qt 4.8.6
    .......


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.