Qt Effort

Sep

4

How to create a simple webservice using qt and libqxt.

By andrerag

LibQxt adds some great functionality to the qt toolkit. One of them is a simple framework for building webservers and services. So here is a simple webservice that adds two numbers and returns the result back to who ever is sending the request.
Obs: the complete source code is available for download below.

First we create our service that will add the numbers and return the result. To do this we extend QxtWebServiceDirectory and reimplement the “indexRequested()” function so we can parse the message and get the parameters.

#include "xmlparser.h"

#define DEFAULT_MESSAGE "<h1>RUN AWAY!</h1>"

class WebService : public QxtWebServiceDirectory {

Q_OBJECT

public:
    WebService(QxtAbstractWebSessionManager * sm , QObject * parent = 0);
    virtual ~WebService();

 protected:
    void indexRequested (QxtWebRequestEvent *event);

private:
    XmlParser *parser;
    QString buildResponse(QString sum, QString actionName);
};

The xml parser is implemented using the qt library, however, the focus here is how to create the webservice.

indexRequested() is called whenever someone sends something to the index url of the service. So if we create a service called “add” and someone sends a SOAP request to “http://SOMEIP:PORT/add/”, indexRequested() will be called. indexRequested() receives a QxtWebRequestEvent*, which is an object that contains all the request information sent by the client. It contains the request headers, session Id, request Id and the message itself.

Below is the code for indexRequested() and buildResponse(). buildResponse() builds the response(duh!) using the SOAP protocol, so the client can understand what is being sent back.

void WebService::indexRequested(QxtWebRequestEvent *event)
{
    qDebug() << "Request Headers: ";

    QHash::const_iterator i = event->headers.constBegin();

     while (i != event->headers.constEnd()) {
         qDebug() << i.key() << ": " << i.value();
         ++i;
     }

    if (event->method.compare("POST")==0) {
        QxtWebContent *myContent = event->content;
        qDebug() << "Bytes to read: " << myContent->unreadBytes();
        myContent->waitForAllContent();
        QByteArray requestContent = myContent->readAll();

        qDebug() << "Content: ";
        qDebug() << requestContent;
        parser->parseSOAP(requestContent);

        QString num1 = parser->getNumber1();
        QString num2 = parser->getNumber2();
        QString sum;

        if (num1!="" && num2!="") {
            sum.setNum(num1.toInt()+num2.toInt());
            QString bodyMessage = buildResponse(sum,"add");
            qDebug() << bodyMessage;
            postEvent(newQxtWebPageEvent(event->sessionID,
                                         event->requestID,
                                         bodyMessage.toUtf8()));
        } else {
            QString errorXml = buildResponse("0","add");
            postEvent(new QxtWebPageEvent(event->sessionID,
                                          event->requestID,
                                          errorXml.toUtf8()));
        }
    } else if (event->method.compare("GET")==0) {
        postEvent(new QxtWebPageEvent(event->sessionID,
                                      event->requestID,
                                      DEFAULT_MESSAGE));
    }
}

QString WebService::buildResponse(QString sum, QString actionName)
{
    QString body;
    body.append("<?xml version=\"1.0\"?>\r\n");
    body.append("<s:Envelope
                 xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"
                 s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">
                 \r\n");
    body.append("<s:Body>\r\n");
    body.append("<u:"+actionName+"Response
                 xmlns:u=\"urn:schemas-upnp-org:service:somador:1\">
                 \r\n");
    body.append("<"+actionName+">"+sum+"</"+actionName+">\r\n");
    body.append("</u:"+actionName+"Response>\r\n");
    body.append("</s:Body>\r\n");
    body.append("</s:Envelope>\r\n");
    return body;
}

We now create a webserver by extending QxtHttpSessionManager and reimplementing the “incomingRequest()” function, so we can see if someone is requesting something.

#include "webservice.h"

class WebServer : public QxtHttpSessionManager {

Q_OBJECT

public:
    WebServer(const QHostAddress &host , quint16 port);
    virtual ~WebServer();

    void addService(QString uri,WebService *newService);

signals:
    void postReceived(QByteArray content);

protected:
    void incomingRequest(quint32 requestID,
                         const QHttpRequestHeader & header,
                         QxtWebContent *deviceContent);

private:
    WebService *rootService;
};

WebServer::WebServer(const QHostAddress &host,quint16 port)
{
    QxtHttpSessionManager(this);
    rootService = new WebService(this,this);
    setPort(port);
    setListenInterface(host);
    setConnector(HttpServer);
    setStaticContentService(rootService);

    qDebug() << "WebServer Started!";
}

WebServer::~WebServer()
{
    delete rootService;
}

void WebServer::incomingRequest(quint32 requestID,
                                const QHttpRequestHeader & header,
                                QxtWebContent *deviceContent)
{
    QxtHttpSessionManager::incomingRequest(requestID, header, deviceContent);
    qDebug() << "Request: "<< requestID;
    qDebug() << "Method: " << header.method();
    qDebug() << "URI: " << header.path();
}

void WebServer::addService(QString uri,WebService *newService)
{
    rootService->addService(uri,newService);
}

Then we simply create a WebServer and a WebService in our main application, add the webservice into the webserver and call “start()”.

    WebServer *myWebServer = new WebServer(QHostAddress("192.168.1.152"),12345);
    WebService *sum = new WebService(myWebServer,0);

    myWebServer->addService("add",sum);
    myWebServer->start();

3 Responses so far

I want to quote your post in my blog. It can?
And you et an account on Twitter?

Good Morning!!! efforts.embedded.ufcg.edu.br is one of the most outstanding resourceful websites of its kind. I take advantage of reading it every day. efforts.embedded.ufcg.edu.br rocks!

The author of efforts.embedded.ufcg.edu.br has written an excellent article. You have made your point and there is not much to argue about. It is like the following universal truth that you can not argue with: There is always someone more intelligent than you (and they will NEVER call when you do tech support). Thanks for the info.

Leave a comment