FastCGI C++ Class library (fcgicc)

Introduction

This is a simple C++ class library that provides FastCGI server functionality. FastCGI is a protocol for connecting web servers with programs that generate content. The protocol is described in detail at the FastCGI website. This library provides a single class which handles FastCGI connections on TCP/IP or local domain sockets. Multiple connections are handled in a single thread using select(). When a request is ready, it is passed to an application-supplied callback for processing, after which the generated response is sent back to the client.

The current version of the library is 0.1.3. It provides a full implementation of the responder mode of FastCGI, but has undergone only limited testing.

License

fcgicc is free software with a BSD-style license. It is provided in the hope that it will be useful, but with absolutely no warranty. See the file LICENSE.txt for details.

Download

Source code:

archive fcgicc-0.1.3.tar.bz2 (12.27 KB; 2013-02-10)

Installing

This library depends on the FastCGI Development Kit from the FastCGI website. For convenience the required part of it is included in this distribution and will be used if the development kit is not found on your system.

To build and install fcgicc as a standalone library you will need CMake, which is available from the CMake website.

To build and install the library, run

cd fcgicc
cmake .
make install

To install it for a single user, run

cd fcgicc
cmake -DPREFIX=$HOME/local .
make install

Alternatively, it may be simpler to import the two source files into your project and build them as part of it. The factcgi.h header from the FastCGI Development Kit must be on the include path in this case.

Using

Here is how it works:

Client ------------> Web server ------> FastCGIServer ----------------.
        HTTP request             params                FastCGIRequest |
                                     in                               '
                                                                Application
                                                                      .
                                                                      |
Client <------------ Web server <------ FastCGIServer <---------------'
       HTTP response            out                   FastCGIRequest
                                err

The web server, which is a client to the FastCGI server, forwards a request as a set of key-value parameter pairs and a standard input stream. The parameter pairs are the environment variables from plain CGI, and they include such important variables as REQUEST_URI. The standard input stream contains data from POST requests.

An instance of the FastCGIServer class listens for requests from the web server, builds a FastCGIRequest instance for each one, calls event handlers defined by the application to process them, and responds to the web server.

The application processes requests using event handlers like this:



#include <fcgicc.h>



int handle_request(FastCGIRequest& request) {
    // This is always the first event to occur.  It occurs when the
    // server receives all parameters.  There may be more data coming on the
    // standard input stream.

    if (request.params.count("REQUEST_URI"))
        return 0;  // OK, continue processing
    else
        return 1;  // stop processing and return error code
}

int handle_data(FastCGIRequest& request) {
    // This event occurs when data is received on the standard input stream.
    // A simple string is used to hold the input stream, so it is the
    // responsibility of the application to remember which data it has
    // processed. The application may modify it; new data will be appended
    // to it by the server. The same goes for the output and error streams:
    // the application should append data to them; the server will remove
    // all sent data from them.

    std::transform(request.in.begin(), request.in.end(),
        std::back_inserter(request.err),
        std::bind1st(std::plus<char>(), 1));
    request.in.clear();  // don't process it again
    return 0;  // still OK
}

class Application {
public:
    int handle_complete(FastCGIRequest& request) {
        // The event handler can also be a class member function. This
        // event occurs when the parameters and standard input streams are
        // both closed, and thus the request is complete.

        request.out.append("Content-Type: text/plain\r\n\r\n");
        request.out.append("You requested: ");
        request.out.append(request.params[std::string("REQUEST_URI")]);
        return 0;
    }
};

The application sets up the FastCGI server like this:



FastCGIServer server; // Instantiate a server

// Set up our request handlers
server.request_handler(&handle_request);
server.data_handler(&handle_data);
server.complete_handler(application, &Application::handle_complete);

server.listen(7000);        // Listen on a TCP port
server.listen(7001);        // ... or on two
server.listen("./socket");  // ... and also on a local doman socket

server.process(100); // Process some data, but don't wait more
                     // than 100 ms for it to arrive

server.process(); // Process some data with no timeout

server.process_forever(); // Process everything