Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Can't Successfully Login With QNetworkReply* (REST API)
QtWS25 Last Chance

Can't Successfully Login With QNetworkReply* (REST API)

Scheduled Pinned Locked Moved Unsolved General and Desktop
qt5.14.2qnetworkrequestrestful apipostlogin
12 Posts 3 Posters 2.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    surferbrain
    wrote on last edited by
    #1

    Hi, I am trying to successfully receive a token so I can receive and edit data from a website (REST API) I control.
    In order to do this, a header in the form of

    header = {"accept": "application/json", "Content-Type": "application/json"}
    
    

    and data in the form of

    datas= {"username": "admin", "password": "pass1234"}
    

    must be passed thorough a post request in order to work. I have already accomplished this successfully to the website with Python code I have written here:

    l = requests.post("http://coolwebsite.com:3245/login", data=json.dumps(datas), headers=header)
    

    When I try to implement this in C++ thorough Qt using the code below, I receive nothing back in replyPost or postResponse. replyPost is shown in the debugger with a value of "". Any help or insight is appreciated!

        //DATA
        QByteArray datas = "{\"username\":\"admin\",\"password\":\"pass1234\"}";
        //Create Request
        QUrl serviceURL("http://coolwebsite.com:3245/login");
        QNetworkRequest request(serviceURL);
        //HEADER
        request.setRawHeader("accept", "application/json");
        request.setRawHeader("Content-Type", "application/json");
        //Execute
        QNetworkAccessManager qnam;
        QNetworkReply* replyPost = qnam.post(request, datas);
        QByteArray postResponse = replyPost->readAll();
        qDebug() << postResponse;
        qDebug() << qPrintable(postResponse);
    

    Here is a screenshot of the variable explorer just after the last line executes :
    5fe8f25c-7875-428d-9dcf-3d68fbe4d7bd-image.png

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      QNetworkAccessManager and QNetworkReply are asynchronous classes. To get the data you have to connect a slot to the reply finished signal. There you will be able to use readAll.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      S 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi and welcome to devnet,

        QNetworkAccessManager and QNetworkReply are asynchronous classes. To get the data you have to connect a slot to the reply finished signal. There you will be able to use readAll.

        S Offline
        S Offline
        surferbrain
        wrote on last edited by surferbrain
        #3

        @SGaist Thank you so much for the quick reply. I decided to write this:

            connect(&qnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkData(QNetworkReply*))); //ADDED
        //DATA
            QByteArray datas = "{\"username\":\"admin\",\"password\":\"pass1234\"}";
            //Create Request
            QUrl serviceURL("http://coolwebsite.com:3245/login");
            QNetworkRequest request(serviceURL);
            //HEADER
            request.setRawHeader("accept", "application/json");
            request.setRawHeader("Content-Type", "application/json");
            //Execute
            QNetworkAccessManager qnam;
            QNetworkReply* replyPost = qnam.post(request, datas);
            QByteArray postResponse = replyPost->readAll();
            qDebug() << postResponse;
            qDebug() << qPrintable(postResponse);
        

        and this respectively in the .h

        public slots:
            void handleNetworkData(QNetworkReply*);
        

        It now provides this error when attempting to run. I have already tried qmake:
        moc_restWindow.obj:-1: error: LNK2019: unresolved external symbol "public: void __cdecl RestWindow::handleNetworkData(class QNetworkReply *)" (?handleNetworkData@RestWindow@@QEAAXPEAVQNetworkReply@@@Z) referenced in function "private: static void __cdecl RestWindow::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void * *)" (?qt_static_metacall@RestWindow@@CAXPEAVQObject@@W4Call@QMetaObject@@HPEAPEAX@Z)

        cc674351-92aa-45a0-9d7e-890a57f2e3e6-image.png

        EDIT: Looks like the error might just be due to it not being able to see a moc_restWindow.obj, but this was never an issue before implementing the modifications above and nothing else.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Did you forget to add the Q_OBJECT macro in your class declaration ?
          If so then do it and then for a re-run of qmake, if it's already there, for a re-run of qmake.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • S Offline
            S Offline
            surferbrain
            wrote on last edited by surferbrain
            #5

            Q_OBJECT is already placed in my .h:

            #ifndef RESTWINDOW_H
            #define RESTWINDOW_H
            
            #include <QDialog> //including QDialog
            #include <QNetworkAccessManager>
            #include <QNetworkReply>
            #include "global.h"
            
            namespace Ui {
            class RestWindow;
            }
            
            class RestWindow : public QDialog
            {
                Q_OBJECT //here it was already placed
            
            public:
                explicit RestWindow(vendor *vendor, QWidget *parent = nullptr);
                ~RestWindow();
                void checkDirectory();
                QNetworkAccessManager qnam;
                vendor *m_vendor;
                QUrl url;
                QNetworkReply *reply;
                QFile *file;
                bool httpRequestAborted;
                long long totalBytesRead;
                QFile *openFileForWrite(const QString &fileName);
                QString *dir;
                QString *fileName;
                dataBase *dbase;
            
            public slots:
                void httpFinished();
                void httpReadyRead();
                void startRequest(const QUrl &requestedUrl);
                void slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator);
                void startDownload();
                void cancelDownload();
                void authenChanged();
                void networkReplyProgress(qint64 bytesRead, qint64 totalBytes);
                void dataBaseChanged();
                void handleNetworkData(QNetworkReply*); //added
            private:
                Ui::RestWindow *ui;
            };
            
            #endif // REST_H
            

            Is this the proper implementation of Q_OBJECT?
            If so, what would the next step be to solve this error?

            Edit: I just reran qmake again successfully.
            Edit2: It is also outputting a LNK1120 error:
            5fc304df-d0bb-43f7-addc-832f6e27a038-image.png

            Edit3: restWindow.cpp and .h are correctly mentioned in the .pro file
            Edit4: It sees moc_restWindow.obj when I move the file from the debug folder to my Desktop. When I place it back it no longer sees it again.

            Edit5: If I comment out every modification I have made, and remove from .h what I added

            void handleNetworkData(QNetworkReply*);
            

            It works perfectly fine. When I uncomment the line above, the error returns. Is this a bug?

            B 1 Reply Last reply
            0
            • S surferbrain

              Q_OBJECT is already placed in my .h:

              #ifndef RESTWINDOW_H
              #define RESTWINDOW_H
              
              #include <QDialog> //including QDialog
              #include <QNetworkAccessManager>
              #include <QNetworkReply>
              #include "global.h"
              
              namespace Ui {
              class RestWindow;
              }
              
              class RestWindow : public QDialog
              {
                  Q_OBJECT //here it was already placed
              
              public:
                  explicit RestWindow(vendor *vendor, QWidget *parent = nullptr);
                  ~RestWindow();
                  void checkDirectory();
                  QNetworkAccessManager qnam;
                  vendor *m_vendor;
                  QUrl url;
                  QNetworkReply *reply;
                  QFile *file;
                  bool httpRequestAborted;
                  long long totalBytesRead;
                  QFile *openFileForWrite(const QString &fileName);
                  QString *dir;
                  QString *fileName;
                  dataBase *dbase;
              
              public slots:
                  void httpFinished();
                  void httpReadyRead();
                  void startRequest(const QUrl &requestedUrl);
                  void slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator);
                  void startDownload();
                  void cancelDownload();
                  void authenChanged();
                  void networkReplyProgress(qint64 bytesRead, qint64 totalBytes);
                  void dataBaseChanged();
                  void handleNetworkData(QNetworkReply*); //added
              private:
                  Ui::RestWindow *ui;
              };
              
              #endif // REST_H
              

              Is this the proper implementation of Q_OBJECT?
              If so, what would the next step be to solve this error?

              Edit: I just reran qmake again successfully.
              Edit2: It is also outputting a LNK1120 error:
              5fc304df-d0bb-43f7-addc-832f6e27a038-image.png

              Edit3: restWindow.cpp and .h are correctly mentioned in the .pro file
              Edit4: It sees moc_restWindow.obj when I move the file from the debug folder to my Desktop. When I place it back it no longer sees it again.

              Edit5: If I comment out every modification I have made, and remove from .h what I added

              void handleNetworkData(QNetworkReply*);
              

              It works perfectly fine. When I uncomment the line above, the error returns. Is this a bug?

              B Offline
              B Offline
              Bonnie
              wrote on last edited by Bonnie
              #6

              @surferbrain Have you implemented handleNetworkData in your .cpp?

              S 1 Reply Last reply
              0
              • B Bonnie

                @surferbrain Have you implemented handleNetworkData in your .cpp?

                S Offline
                S Offline
                surferbrain
                wrote on last edited by
                #7

                @Bonnie Ohhh, so handleNetworkData is a function I have to write? My misunderstanding. I will try this now.

                B 1 Reply Last reply
                0
                • S surferbrain

                  @Bonnie Ohhh, so handleNetworkData is a function I have to write? My misunderstanding. I will try this now.

                  B Offline
                  B Offline
                  Bonnie
                  wrote on last edited by
                  #8

                  @surferbrain But instead of QNetworkAccessManager::finished, we usually connect the QNetworkReply::finished signal.
                  I see you already have a slot named httpFinished, which signal does it connect to and what does it do?

                  S 1 Reply Last reply
                  0
                  • B Bonnie

                    @surferbrain But instead of QNetworkAccessManager::finished, we usually connect the QNetworkReply::finished signal.
                    I see you already have a slot named httpFinished, which signal does it connect to and what does it do?

                    S Offline
                    S Offline
                    surferbrain
                    wrote on last edited by surferbrain
                    #9

                    @Bonnie @SGaist
                    Hi, I was able to switch around several things, along with a much better understanding of connect().

                    void RestWindow::startRequest(const QUrl &requestedUrl) //after startDownload
                    {
                        url =requestedUrl; //should be url from json file
                        //DATA
                        QByteArray datas = "{\"username\":\"admin\",\"password\":\"pass1234\"}";
                        // Time for building your request
                        QUrl loginURL("http://coolwebsite:1234/login");
                        QNetworkRequest request(loginURL);
                        //HEADER
                        request.setRawHeader("accept", "application/json");
                        request.setRawHeader("Content-Type", "application/json");
                        reply = qnam.post(request, datas);
                        connect(reply, &QNetworkReply::finished, this, &RestWindow::postFinished); 
                    }
                    
                    
                    void RestWindow::postFinished(){
                        QByteArray postResponse = reply->readAll();
                        qDebug() << postResponse;
                        qDebug() << qPrintable(postResponse);
                    }
                    

                    httpFinished is the function I created to write the eventual get request response to a file. I can't even receive the correct credential back from logging in. I am focusing on trying to login as of now.

                    The post request hangs the code for about 10-15 seconds. After, slot postFinished is triggered. postResponse = reply->readAll() returns a value of "" as seen in the variable explorer. I should be seeing at the very least a token value.

                    Perhaps I am not placing the correct data where it is needed to be in QNetworkRequest request or in datas? Here is the curl command equivalent that is used to log on:

                    curl -X POST "http://coolwebsite:1234/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"username\": \"admin\", \"password\": \"pass1234\"}"
                    
                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      You can use wireshark to check the difference between the two request sent. Or something like https://requestbin.com

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      S 1 Reply Last reply
                      0
                      • SGaistS SGaist

                        You can use wireshark to check the difference between the two request sent. Or something like https://requestbin.com

                        S Offline
                        S Offline
                        surferbrain
                        wrote on last edited by surferbrain
                        #11

                        @SGaist Hey! Just ran the above code (with qnam.post() inside the startRequest()) and no signal reaches the pipedream.net I created. My Python code reaches it just fine. Is there something fundamentally wrong with my code that I have not considered?

                        Edit: Just found that it looks like it is showing:
                        qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed
                        QIODevice::read (QNetworkReplyHttpImpl): device not open
                        This is strange as I already downloaded and modified the PATH for the Toolkit I use, but now the PATH variable looks unmodified.

                        I was using openSSL1.0.2p before, but now when I run

                        qDebug() << QSslSocket::sslLibraryBuildVersionString();
                        

                        at the end of my code it displays "OpenSSL 1.1.1d 10 Sep 2019"
                        Was there an update to Qt recently that could have changed this in the past few days? It's showing the same issue with another qt project that used to work about a week ago.

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          Not in the past few days, IIRC, OpenSSL 1.1 support started with 5.10 and the ore-built package switched to it during the 5.12 release cycle.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved