Rest client with Qt 4.5

It’s very easy to call a rest service from qt, even with authentication,
using QtNetwork/QNetworkAccessManager class
http://doc.trolltech.com/4.5/qnetworkaccessmanager.html.

Using the previous rest servlet sample.


    QNetworkAccessManager *manager = new QNetworkAccessManager(this);

    QObject::connect(manager, SIGNAL(finished(QNetworkReply *)),
                              SLOT(slotRequestFinished(QNetworkReply *)));

    QNetworkRequest request;
    request.setUrl(QUrl("http://localhost:8080/restservlet/sample/tommy"));
    request.setRawHeader("Authorization", "Basic " +
                         QByteArray(QString("%1:%2").arg("user").arg("asas").toAscii()).toBase64());
    request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml");

    QNetworkReply *reply = 0;
    reply = manager->get(request);

    QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
                            SLOT(slotProgress(qint64,qint64)));



void SampleRestClient::slotRequestFinished(QNetworkReply *reply)
{
    if (reply->error() > 0) {
        qDebug() <errorString();
    }
    else {
        QDomDocument doc;
        QXmlInputSource is;
        is.setData(reply->readAll());
        doc.setContent(is.data());

        QDomNodeList nodes = doc.elementsByTagName("message");

        if (nodes.size() > 0) {
            qDebug() << nodes.at(0).toElement ().text ();
        }
    }
}

  • We neet to set the Authorization header for the basic http auth mechanism.
    Just “Basic user:password” user and password encoded with base64.
  • We can use QDomDocument to get the xml representation of the rest response.

Here is the complete code sample :

  • main.cpp
    
    #include "mainwindow.h"
    
    #include <QtGui/QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    
    
  • mainwindow.h

    
    #ifndef MAINWINDOW_H                                                        
    #define MAINWINDOW_H                                                        
    
    #include <QtGui/QWidget>
    
    class QLabel;
    class QProgressBar;
    class QNetworkAccessManager;
    class QNetworkReply;
    
    class MainWindow : public QWidget
    {
        Q_OBJECT
    public:
        MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private slots:
        void slotRequestFinished(QNetworkReply *);
        void slotSetProgress(qint64, qint64);
    
    private:
        QLabel *m_label;
        QProgressBar *m_progress;
    
        QNetworkAccessManager *m_network;
    };
    
    #endif // MAINWINDOW_H
    
    
  • mainwindow.cpp

    
    #include "mainwindow.h"                                                       
    
    #include <QDebug>
    #include <QThread>
    #include <QtCore/QUrl>
    #include <QtGui/QLabel>
    #include <QtGui/QProgressBar>
    #include <QtGui/QVBoxLayout>
    #include <QtNetwork/QNetworkAccessManager>
    #include <QtNetwork/QNetworkRequest>
    #include <QtNetwork/QNetworkReply>     
    #include <QtNetwork/QNetworkProxy>
    #include <QtXml/QDomDocument>
    
    static const char *REQUEST_URL = "http://localhost:8080/restservlet/rest/sample/tommy";
    static const char *USER = "user";                                                      
    static const char *PASSWORD = "asas";                                                  
    
    MainWindow::MainWindow(QWidget *parent)
        : QWidget(parent)                  
    {                                      
        QVBoxLayout *layout = new QVBoxLayout(this);
    
        m_label = new QLabel();
        m_progress = new QProgressBar();
        m_progress->setRange(0, 100);   
    
        layout->addWidget(m_label);
        layout->addWidget(m_progress);
        setLayout(layout);            
    
        m_network = new QNetworkAccessManager(this);
        QNetworkRequest request;                    
        request.setRawHeader("Authorization", "Basic " +
                             QByteArray(QString("%1:%2").arg(USER).arg(PASSWORD).toAscii()).toBase64());
        request.setUrl(QUrl(REQUEST_URL));                                                              
        QNetworkReply *reply = m_network->get(request);                                                 
    
        QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
                                SLOT(slotSetProgress(qint64,qint64)));  
        QObject::connect(m_network, SIGNAL(finished(QNetworkReply *)),  
                                    SLOT(slotRequestFinished(QNetworkReply *)));
    }                                                                           
    
    MainWindow::~MainWindow()
    {                        
    }                        
    
    void MainWindow::slotRequestFinished(QNetworkReply *reply)
    {                                                         
        m_progress->setValue(0);
    
        if (reply->error() > 0) {
            m_label->setText("Error number = " + reply->errorString());
        }
        else {
            QByteArray data = reply->readAll();
            QDomDocument doc;
            doc.setContent(data);
            QDomNodeList nodes = doc.elementsByTagName("message");
    
            if (nodes.size() > 0) {
                m_label->setText(nodes.at(0).toElement().text());
            }
        }
    }
    
    void MainWindow::slotSetProgress(qint64 received, qint64 total)
    {
        if (total > 0 && received > 0) {
            m_progress->setValue((int) total / received);
        }
    }
    
    
  • sample.pro

    
    QT       += network xml
    
    TARGET = sample_rest_client
    TEMPLATE = app
    
    
    SOURCES += main.cpp\
            mainwindow.cpp
    
    HEADERS  += mainwindow.h
    
    
  • qmake && make && ./sample_rest_client to try it!

qt rest client sample

Advertisements
    • Eduardo
    • July 7th, 2009

    My friend,

    Thanks for this sample. You really helped me a lot!! šŸ™‚

    Thanks again!

    • Soham
    • January 28th, 2010

    Wow, this looks really amazing. Was searching for this everywhere and finally found it. Will try it out and let you now. Thanks a ton!!!

    • Soham
    • February 6th, 2010

    Hi any idea of how to get attributes with a tag/element like content, using the above I can only extract “content” in the node list, any pointers on how i can extract “name” or “alpha” or “name=alpha”?

    • Nick
    • February 19th, 2010

    Thanks a lot, this sample really cleared a lot of things for me šŸ™‚

    • Greg K
    • April 29th, 2010

    I’ve been trying to get this example to work synchronously using the 4.7 preview. In the constructor of MainWindow before the connections are made, I put the following calls:

    reply->waitForReadyRead(-1);
    QByteArray data = reply->readAll();
    QString dataStr(data);
    qDebug() << "received response synchronously <" << dataStr <“;

    According to the Qt documentation this should block until the response arrives, but it returns immediately and prints out an empty string as its response. Does anyone have an idea why this might be? Am I doing something wrong, or is this a bug in the 4.7 preview?

      • jgoday
      • May 6th, 2010

      hi,
      I cannot make it work ( waitForReadyRead(-1) ) with 4.6 neither,
      but a simple way of doing that would be using QEventLoop

      Here’s a sample http://github.com/jgoday/sample_sync_network

    • waitForReadyRead() is not reimplemented in QNetworkReply, the default implementation of QIODevice::waitForReadyRead() does nothing, and returns false.

    • erha
    • March 2nd, 2011

    You might need to deleteLater the reply in the slotRequestFinished.

  1. Appreciating the commitment you put into your website and in depth information you offer.

    It’s good to come across a blog every once in a while that isn’t the same outdated rehashed material.
    Great read! I’ve bookmarked your site and I’m including
    your RSS feeds to my Google account.

  2. Hi there just wanted to give you a quick heads up.
    The words in your content seem to be running off the screen in Firefox.
    I’m not sure if this is a formatting issue or something to do with internet browser compatibility but I figured I’d post to let you know.
    The layout look great though! Hope you get the problem solved soon.
    Thanks

  3. Heya i am for the primary time here. I came across this board and I
    to find It truly helpful & it helped me out a lot.
    I hope to present something back and aid others such
    as you helped me.

  1. November 23rd, 2012

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: