I'd like to write a small HTTP server application that receives HTTP GET requests, processes them and sends out a reply. Because of the history of the application I'd favor using Qt for this, but all I can find is the other (more common) direction: Send a request to a server and receive a reply using QNetworkAccessManager. What I need is something like a socket that, when a request comes in, produces an object where I can pick url etc. of this request, so I can send out an appropriate reply.
Am I just blind or is nothing like this in the Qt framework? If so, can you recommend alternatives?
I found this https://github.com/vinipsmaker/tufao , Its a late answer .. not sure if it helps.
QtWebApp is a HTTP server with support of GET and POST method, cookies, sessions and file uploads. Using this library is as simple as writing a Java Servlet.
The project website is in german, however the downloadable files are all in english, including the documentation.
I have just released the first version of QHttpEngine, which aims to fill the gap that you've described. The goal of the project is to provide an extremely simple set of classes that provide an HTTP server that integrates with Qt.
For example, to serve static files from resources in your application, all you would need to do is:
QFilesystemHandler handler(":/www");
QHttpServer server(&handler);
server.listen(QHostAddress::LocalHost, 8000);
You can also create a class derived from QObject
that expose its slots as endpoints in an HTTP API. For example:
class ApiHandler : public QObjectHandler
{
Q_OBJECT
private slots:
QVariantMap doSomething(const QVariantMap ¶ms) {
// do something with the parameters and return a response
}
};
Users can then send a POST request to /doSomething
with the parameters encoded as JSON and receive the response that the slot generates.
The entire library is fully documented and comes with a rather exhaustive test suite. It is cross-platform and is officially tested and supported on Linux, Windows, and Mac OS X. There is at least one major open-source application using QHttpEngine, NitroShare.
The above simple server had issues running on MSwindows operating systems as it would lockup after a while. This was due to waitForReadyRead() operating in a random fashion on MS systems. The program below waitForReadyRead() was replaced with an event loop using readyRead() signal.
# Project file
QT += core
QT += network
QT -= gui
TARGET = webServer
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
HEADERS += myhttpserver.h
//-----------myhttpserver.h--------------
#ifndef MYHTTPSERVER
#define MYHTTPSERVER
#include <QCoreApplication>
#include <iostream>
#include <QObject>
#include <QTcpSocket>
#include <QTcpServer>
#include <QIODevice>
class myHTTPserver : public QObject
{
Q_OBJECT
public:
explicit myHTTPserver(QObject *parent = 0);
~myHTTPserver();
QTcpSocket *socket ;
public slots:
void myConnection();
void txRx();
void closingClient();
private:
qint64 bytesAvailable() const;
QTcpServer *server;
};
#endif // MYHTTPSERVER
//------------------------ main.cpp ----------------------
#include "myhttpserver.h"
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
myHTTPserver server;
return a.exec();
}
myHTTPserver::myHTTPserver(QObject *parent) : QObject(parent)
{
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()),this, SLOT(myConnection()));
if(!server->listen(QHostAddress::Any,8080))cout<< "\nWeb server could not start";
else cout<<"\nWeb server is waiting for a connection on port 8080";
}
void myHTTPserver::myConnection()
{
socket = server->nextPendingConnection();
connect(socket, SIGNAL(readyRead()), this, SLOT(txRx()));
connect(socket, SIGNAL(disconnected()), this, SLOT(closingClient()));
}
void myHTTPserver::txRx()
{
char webBrowerRXData[1000];
int sv=socket->read(webBrowerRXData,1000);
cout<<"\nreading web browser data\n";
for(int i=0;i<sv;i++)cout<<webBrowerRXData[i];
cout<<"\n";
socket->write("HTTP/1.1 200 OK\r\n"); // \r needs to be before \n
socket->write("Content-Type: text/html\r\n");
socket->write("Connection: close\r\n");
socket->write("Refresh: 1\r\n"); //refreshes web browser every second. Require two \r\n.
socket->write("Pragma: no-cache\r\n");
socket->write("\r\n");
socket->write("<!DOCTYPE html>\r\n");
socket->write("<html><body>Number of seconds since connected.. ");
QByteArray str;
static qint16 count; //count number to be displayed on web browser
str.setNum(count++); //convert int to string
socket->write(str);
socket->disconnectFromHost();
}
void myHTTPserver::closingClient()
{
socket->deleteLater();
}
myHTTPserver::~myHTTPserver()
{
cout<<"\nclosing socket\n";
socket->close();
}
QttpServer = Qt + libuv + REST = your API server
For an Qt API server that need to handle a large number of concurrent connections, request, and what-have-you... we have the libuv library.
Though libuv is built for NodeJS, we fans in Qt-land can still benefit from epolls and kqueues instead of the default select method.
See more on github https://github.com/supamii/QttpServer
QhttpServer seems to do exactly what you need. unfortunately it does not seem to be very active.
Here is simple Qt server that can be used from QML, pure-JS HTTP processing: https://github.com/ncp1402/ql-server
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With