Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Examples

Currently, there are three approaches, how you can interface the FastCGI protocol.

Simple loop

The easiest way to write a FastCGI-capable application is taken directly from the original fastcgi library. At first, one creates a connection, secondly a request which is attached to the former. A loop is then created, which serves one request per cycle.

If you run the program as a CGI binary, the first FastCGIRequest.accept() call returns true, subsequent calls return false, indicating that the request is finished and the application should quit.

import  fcgi.Request;
import  fcgi.Connection;

int main (char[][] args)
{
//  Also possible, because null as a connection means to listen on filedescriptor 0.
//  This is possible for all cases (loop, thread and application)!
//
//    FastCGIConnection connection = new FastCGIConnection ();
//    FastCGIRequest request = new FastCGIRequest (connection);

    FastCGIRequest request = new FastCGIRequest ();


    while ( request.accept () )
    {
        request.stdout.write("Content-type: text/html\r\n\r\n");
        request.stdout.write("Hello world!\n");
        request.exitStatus = 0;
    }
    return request.exitStatus;
}

For a more complex example, take a look at the VerboseLoop example.

Thread loop

As web applications tend to be only slow if they must wait for other services like databases or directory servers and the world of multi-core CPUs grows, one might think of threaded web applications.

The following application does the same things as the Simple loop did, using threads.

import  fcgi.Thread;
import  fcgi.Connection;
import  fcgi.Request;

int run(FastCGIRequest request)
{
    request.stdout.write("Content-type: text/html\r\n\r\n");
    request.stdout.write("Hello world!\n");

    return 0;
}

int main(char[][] args)
{
    FastCGIConnection connection = new FastCGIConnection ();

    return FastCGIThread.loop(connection, &run, true, 10);
}

The only interesting things are the parameters for FastCGIThread.loop:

  • An open FastCGIConnection
  • Function pointer to your request-handler routine
  • A boolean variable if you want the library to throw Exceptions on faults.
  • The number of threads.

For a more complex example, take a look at the VerboseThread example.

Application class

For more complex and performance-critical applications, you might need some variables (e.g. for caching) for each thread, which should not get initialized once every request to avoid heap activity and database queries.

The following application once more does the same things as the examples above did but uses an Object Oriented Programming approach to provide the needed structure.

import  fcgi.Application;
import  fcgi.Connection;
import  fcgi.Request;

import tango.text.convert.Layout;
import tango.io.Print;
import tango.io.Buffer;

class MyApp : FastCGIApplication
{
    private Print!(char) stdout;
    private Print!(char) stderr;

    this (int id, FastCGIRequest request)
    {
        auto layout = new Layout!(char) ();
        stdout = new Print!(char) (layout, request.stdout);
        stderr = new Print!(char) (layout, request.stderr);
    }

    int run()
    {
        stdout ("Content-type: text/html\r\n\r\n");
        stdout ("Hello world!\n") ();

        return 0;
    }
}

int main(char[][] args)
{
    FastCGIConnection connection = new FastCGIConnection ();

    return FastCGIApplication.loop!(MyApp) (connection, true, 10);
}

The above example shows the OOP way of using FastCGI. It should be faster than the simple threaded example, because the former creates Printer,Layout and Buffer to stdin for every request, which is done here in the constructor and thus only done on thread creation.

For a more complex example, take a look at the VerboseApp example.

Exceptions

D uses exceptions for error handling. Inside thread- and application-loops one can also use exceptions, which are - if not caught by the loop method itself - automatically reported to stderr, resulting in an entry in the errorlog of your webserver.

The following application generates a random number and according to it, raises various exceptions. Especially all errors that would result in segmentation faults or asserts are reported to stderr, instead of silently killing the program as those would do in C/C++. Of course, this does not work if you compile with -release!

import  fcgi.Thread;
import  fcgi.Connection;
import  fcgi.Request;
import  fcgi.Exception;

import  tango.math.Random;

Random rnd;

int myrun(FastCGIRequest request)
{
    request.stdout.write ("Content-type: text/html\r\n\r\n");

    switch (rnd.next(4))
    {
    case 0:
        request.stdout.write ("Chosen exception: Array index out of bounds\n");
        char[] foo = new char[3];
        char c = foo[10];
    break;
    case 1:
        request.stdout.write ("Chosen exception: Assertion\n");
        assert (false);
    break;
    case 2:
        request.stdout.write ("Chosen exception: Exception\n");
        throw new Exception ("My Exception");
    break;
    default:
        request.stdout.write ("Chosen Exception: none\n");
    }

    return 0;
}

int main(char[][] args)
{
    rnd = new Random ();
    FastCGIConnection connection = new FastCGIConnection ();

    return FastCGIThread.loop(connection, &myrun, true, 10);
}