Skip to content

Latest commit

 

History

History
234 lines (186 loc) · 8.57 KB

README.md

File metadata and controls

234 lines (186 loc) · 8.57 KB

QHttp

This project is a backport of azadkuh/qhttp for Qt5.3+ and C++11 (instead of Qt5.5+ and C++14). It fits the last version of azadkuh/qhttp and no issue has been reported at the moment.

Read more about motivations here.

Table of contents

About

TOC

QHttp is a lightweight, asynchronous and fast HTTP library in C++11 / Qt5.3+, containing both server and client side classes for managing connections, parsing and building HTTP requests and responses.

  • the objective of QHttp is being light weight with a simple API for Qt developers to implement RESTful web services in private (internal) zones. more
  • by using std::function and C++11 lambda, the API is intentionally similar to the Node.js' http module. Asynchronous and non-blocking HTTP programming is quite easy with QHttp. have a look at sample codes.
  • the fantastic nodejs/http-parser (which is a single pair of *.h/*.c files) is the only dependency of the QHttp.

This project was inspired by nikhilm/qhttpserver effort to implement a Qt HTTP server. QHttp pushes the idea further by implementing client side classes, better memory management, a lot more Node.js-like API, ...

Sample codes

TOC

a HelloWorld HTTP server by QHttp looks like:

int main(int argc, char** argv) {
    QCoreApplication app(argc, argv);

    using namespace qhttp::server;
    QHttpServer server(&app);
    server.listen( // listening on 0.0.0.0:8080
        QHostAddress::Any, 8080,
        [](QHttpRequest* req, QHttpResponse* res) {
            // http status 200
            res->setStatusCode(qhttp::ESTATUS_OK);
            // the response body data
            res->end("Hello World!\n");
            // automatic memory management for req/res
    });

    if ( !server.isListening() ) {
        qDebug("failed to listen");
        return -1;
    }

    return app.exec();
}

to request weather information by HTTP client:

int main(int argc, char** argv) {
    QCoreApplication app(argc, argv);

    using namespace qhttp::client;
    QHttpClient client(&app);
    QUrl        weatherUrl("http://wttr.in/tehran");

    client.request(qhttp::EHTTP_GET, weatherUrl, [](QHttpResponse* res) {
        // response handler, called when the incoming HTTP headers are ready

        // gather HTTP response data (HTTP body)
        res->collectData();

        // when all data in HTTP response have been read:
        res->onEnd([&]() {
            writeTo("weather.html", res->collectedData());

            // done! now quit the application
            qApp->quit();
        });

        // just for fun! print incoming headers:
        qDebug("\n[Headers:]");
        res->headers().forEach([](auto cit) {
            qDebug("%s : %s", cit.key().constData(), cit.value().constData());
        });
    });

    // set a timeout for the http connection
    client.setConnectingTimeOut(10000, []{
        qDebug("connecting to HTTP server timed out!");
        qApp->quit();
    });

    return app.exec();
}

Features

TOC

  • the only dependencies are: Qt5.3 minimum, C++11 and the http-parser
  • both TCP and UNIX (local) sockets are supported as backend.
  • separate namespaces for server and client classes.
  • HTTP server classes: QHttpServer, QHttpConnection, QHttpRequest and QHttpResponse.
  • optional HTTP client classes: QHttpClient, QHttpRequest and QHttpResponse. the client classes can be disabled at build time by commenting QHTTP_HAS_CLIENT in common.dir
  • automatic memory management of objects. Instances of connections, requests and replies will be deleted automatically when socket drops or disconnected.
  • PIMPL (Private implementaion) to achieve better ABI compatibility and cleaner API and faster compile time.
  • Asynchronous and non-blocking. You can handle thousands of concurrent HTTP connections efficiently by a single thread, although a multi-threaded HTTP server is easy to implement.
  • high throughput, I have tried the QHttp and gason++ to implement a REST/Json web service on an Ubuntu VPS (dual core + 512MB ram) with more than 5800 connections per second (stress test). On a MacBook Pro (i5 4258U, 8GB ram), QHttp easily reaches to more than 11700 connections / second. Generally QHttp is 1.5x ~ 3x faster than Node.js depending on your machine / OS.
  • Easily portable where ever Qt5 / c++14 works. Tested under:
    • Linux Ubuntu 12.04 ~ 16.04 LTS, g++ 5.3+
    • OS X 10.9+, clang 3.7+
    • Windows 7/8.1, msvs2015 / mingw (g++ 6.1)

Setup

TOC

instructions:

# first clone this repository:
$> git clone https://github.com/azadkuh/qhttp.git
$> cd qhttp

# prepare dependencies:
$qhttp/> qompoter install

*Note: to install Qompoter on your machine, use `npm install -g qompoter` or check [Qompoter documentation](https://github.com/Fylhan/qompoter/blob/master/README.md#installation).*

# now build the library and the examples
$qhttp/> qmake -r qhttp.pro
$qhttp/> make -j 8

Multi-threading

TOC

As QHttp is asynchronous and non-blocking, your app can handle thousands of concurrent HTTP connections by a single thread.

in some rare scenarios you may want to use multiple handler threads (although it's not always the best solution):

  • there are some blocking APIs (QSql, system calls, ...) in your connection handler (adopting asynchronous layer over the blocking API is a better approach).
  • the hardware has lots of free cores and the measurement shows that the load on the main QHttp thread is close to highest limit. There you can spawn some other handler threads.

Source tree

TOC

  • src/: holds the source code of QHttp. server classes are prefixed by qhttpserver* and client classes by qhttpclient*.
    • private/: Private classes of the library.
  • vendor/: will contain http-parser source tree as the only dependency. this directory is created by setup. see also: setup.
  • example/: contains some sample applications representing the QHttp usage:
    • helloworld/: the HelloWorld example of QHttp, both server + client are represented. see: README@helloworld
    • basic-server/: a basic HTTP server shows how to collect the request body, and respond to the clients. see: README@basic-server
    • keep-alive: shows how to keep an http connection open and transmitting many requests/responses. see: README@keep-alive
    • post-collector: another server example shows how to collect large data by POST requests. see: README@post-collector
  • tmp/: a temporary directory which is created while makeing the library and holds all the .o, moc files, etc.
  • xbin/: all the executable and libraries will be placed on this folder by build system.

Disclaimer

TOC

  • Implementing a lightweight and simple HTTP server/client in Qt with Node.js like API, is the main purpose of QHttp.
  • There are lots of features in a full blown HTTP server which are out of scope of this small library, although those can be added on top of QHttp.
  • The client classes are by no mean designed as a QNetworkAccessManager replacement. QHttpClient is simpler and lighter, for serious scenarios just use QNetworkAccessManager which supports proxy, redirections, authentication, cookie jar, ssl, ...
  • I'm a busy person.

If you have any ideas, critiques, suggestions or whatever you want to call it, please open an issue. I'll be happy to hear different ideas, will think about them, and I try to add those that make sense.

License

TOC

Distributed under the MIT license. Copyright (c) 2014, Amir Zamani. Distributed under the MIT license. Copyright (c) 2017, Olivier Maridat.