tufao  0.8.1
An asynchronous web framework for C++ built on top of Qt
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
tufao Documentation

Introduction

Tufão is a web framework for C++ that makes use of Qt's object communication system (signals & slots). It features:

  • High performance standalone server
  • Cross-plataform support
  • Good documentation
  • Support modern HTTP features
    • Persistent streams
    • Chunked entities
    • 100-continue status
    • WebSocket
  • HTTPS support
  • Flexible request router
  • Static file server with support for conditional requests and partial download
  • Plugin-based server to allow change the running code without restart the application
  • Flexible and secure session support
  • QtCreator's plugin to allow create new applications rapidly
  • Timeout support

It uses Ryan Dahl's HTTP parser to provide good performance.

Creating a Tufão-based application

In this section, I assume that you already have installed Tufão libraries and tools (tufao-routes-editor, QtCreator's plugin, ...).

Hello World!

get_started_1.png
QtCreator's Tufão plugin

First of all, you must open QtCreator and go to the new project dialog, you may be able to select Tufão Web Server project from the list of projects in the Tufão category.

get_started_2.png
Tufão Web Server project templates

Go through the pages of the project wizard, selecting the application template. At the end, you'll get an unconfigured qmake-based application. Under QtCreator's interface, go to the projects mode and choose a configuration. If you don't configure the project, QtCreator won't be able to compile your project.

And then, there was the code

You may have a main.cpp file with a code like this:

1 #include <QtCore/QCoreApplication>
2 
3 #include <Tufao/HttpServer>
4 
5 #include <Tufao/HttpServerRequestRouter>
6 #include <Tufao/HttpFileServer>
7 #include <Tufao/HttpPluginServer>
8 
9 #include "notfound.h"
10 
11 int main(int argc, char *argv[])
12 {
13  Q_INIT_RESOURCE(static);
14  // First we create the event loop and the server objects
15  QCoreApplication a(argc, argv);
16  Tufao::HttpServer server;
17 
18  // Then we create a request router and configure it...
20 
21  // ...using some handlers
22 
23  // to allow you change the running code without restart the application
24  Tufao::HttpPluginServer pluginServer("routes.conf", true);
25  // to server static files under public folder
26  Tufao::HttpFileServer fileServer("public");
27  // to respond the remaining requests with a "404 - not found"
28  NotFoundHandler handler404;
29 
30  // you should also create handlers to:
31  // - "/" (maybe redirecting to some other path)
32  // - "/favicon.ico" (to serve the page's icon)
33  router.map(QRegExp(""), &pluginServer)
34  .map(QRegExp(""), &fileServer)
35  .map(QRegExp(""), &handler404);
36 
37  // We set the router as the global request handler
38  QObject::connect(&server, SIGNAL(requestReady(Tufao::HttpServerRequest*,Tufao::HttpServerResponse*)),
39  &router, SLOT(handleRequest(Tufao::HttpServerRequest*,Tufao::HttpServerResponse*)));
40 
41  // Last, we run our server...
42  server.listen(QHostAddress::Any, 8080);
43 
44  // ...and start the event loop
45  return a.exec();
46 }
This class provides a plugin-based request handler.
Definition: httppluginserver.h:55
The Tufao::HttpServerResponse is used to respond to a Tufao::HttpServerRequest.
Definition: httpserverresponse.h:57
This class provides a robust and high performance HTTP request router.
Definition: httpserverrequestrouter.h:67
The Tufao::HttpServer represents a HTTP request received by Tufao::HttpServer.
Definition: httpserverrequest.h:47
HttpServerRequestRouter & map(const QRegExp &path, AbstractHttpServerRequestHandler *handler)
This method maps requests which path components in the url matches the regular expression path to the...
You can use this class to serve static files under Tufão.
Definition: httpfileserver.h:61
bool listen(const QHostAddress &address=QHostAddress::Any, quint16 port=0)
Tells the server to listen for incoming connections on address address and port port.
The Tufao::HttpServer class provides an implementation of the HTTP protocol.
Definition: httpserver.h:54

A main file with 46 lines of code. It's a bunch of code, but if you delete the comments and includes, you'll have only 26 lines remaining. It's possible to create Tufão applications with fewer yet lines, but I'll use this code to explain important Tufão features. They'll prove their value.

Tufão provides a web framework and has its own HTTP server (based on Ryan Dahl's HTTP parser). This design give you greater control over the applications and can really boost its performance. But, as uncle Ben may have told you:

With great power comes great responsibility

This may sound scary to you at first, but don't worry, the Tufão team will do their best to make this responsibility easier to assume, with each realease. But you need to promisse that you'll use Tufão facilities and read the documentation.

To use the Tufão HTTP server, we instantiate, as show in the line 16, a Tufao::HttpServer, put it to listen on port 8080, as show in the line 42, and start a event loop, as show in the line 45. This server will expose all we need to this introduction.

The Tufao::HttpServer will emit the Tufao::HttpServer::requestReady signal each time a request comes. We can handle all requests in a single place in the code, but we won't do that, because... em... as some wise person said before, we need:

Divide and conquer

We could decompose our slot into some functions to do the job. But we won't do that, because Tufão already has a better abstraction for the problem, Tufao::HttpServerRequestRouter.

The idea behind Tufao::HttpServerRequestRouter is have a chain of request handlers and mapped paths to them. If a request comes to a handler unable to handle it, the request is delegated to another handler in the chain.

In the code, we have one router (line 19) and three handlers (lines 24, 26 and 28). In the lines 33 to 35 we bind the router and the handlers and in the line 38 we bind the router and the server. The handlers, in order, are:

  • Tufao::HttpPluginServer: Uses plugins to handle the requests. A plugin mechanism is what allows you to change the running code without restart the application. In this code, we use the file routes.conf (editable with the tufao-routes-editor tool) to configure the plugins and set autoreload to true.
  • Tufao::HttpFileServer: Serve static files. We use the folder public as root dir.
  • NotFoundHandler: A custom class (defined in the files notfound.h and notfound.cpp) that responds to every request with a 404 status code. It will use the file notfound.html embedded in the binary (through the Qt resource system) as message body of the responses. Line 14 init the needed resource.

If you run this application, you'll see the error Unsupported config file version. This is happening because you didn't prepare a routes.conf file to feed the plugin handler. See Tufão's plugin system to learn how to fix it and add a plugin-based handler to the application. The file routes.conf must be placed in the working dir from where the application will run (or is running).

If you access http://localhost:8080/ you'll see a message telling you that the page wasn't found. Create a folder called public in the working dir of the executable and put a file called index.html there:

<html>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <head><title>Hello World</title></head>
  <body>
    <h1>Congratulations,</h1>
    <p>you are able to start web development in C++ with Tufão</p>
  </body>
</html>

Now access the page http://localhost:8080/index.html and see the result. As an exercise, I left the task to add a favicon to your application using the Tufão's plugin system.

Build system integration

The Tufão has native support to three build systems: qmake, pkgconfig and CMake.

Once Tufão is correctly installed, you can use Tufão in your qmake-based applications appending the following line to your project file, where x is the major version (0 for Tufão 0.x) you want to use:

CONFIG += TUFAOx

If you use CMake, just follow the common steps (require package and handle compile and link flags) in your CMakeLists.txt file:

find_package(Tufao 0.4 REQUIRED)
include_directories("${TUFAO_INCLUDE_DIR}")
target_link_libraries(foobar ${TUFAO_LIBRARIES})

If you want to use a FindTufao.cmake file embedded in your project dir, add the following line to your CMakeLists.txt:

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "/path/to/FindTufao.cmake")

If you want to use autotools or another build system that has pkgconfig support, you can use the Tufão's pkgconfig module, where x is the major version (0 for Tufão 0.x) you want to use:

$ pkg-config tufaox

If want to use a build system that don't support pkgconfig, you should be ashamed, but you may still be able to use Tufão (probably editing the compiler -I flag and the linker -L and -l flags).