Embedthis Appweb 3.4.0
Home > Programming Guide > Pipeline Stages

Quick Nav

See Also

Extending via Pipeline Stages

The Appweb request processing scheme can be extended by creating custom pipeline stages. Stages come in three varieties: Handlers, Filters and Network Connectors.

Handlers respond to requests and generate response content, filters permute incoming or outgoing data and connectors transmit responses to the client.

This document describes the pipeline stage interface and how to create Appweb handlers, filters and connectors. See the Configuring Pipeline Stages document for background.

Handlers

The core Appweb HTTP server cannot serve any requests or generate responses by itself. It relies on request handlers to generate response content for HTTP requests. The standard distribution of Appweb is itself comprised of seven different handlers which serve all the content provided by an Appweb server.

Creating a Handler

To create an Appweb handler, you need to call maCreateHandler and supply a unique handler name and flags that modify the behavior of the handler.

The following demonstrates the creation of a "sample" handler.

int maOpenSimpleHandler(MaHttp *http)
{
    MaStage     *handler;
    handler = maCreateHandler(http, "simpleHandler", MA_STAGE_ALL | MA_STAGE_VIRTUAL);
    if (handler == 0) {
        return MPR_ERR_CANT_CREATE;
    }
    /* Define function callbacks */
    handler->run = runSimple;
    handler->parse = parseSimple;
    handler->match = matchSimple;
    handler->open = openSimple;
    handler->close = closeSimple;
    handler->incomingData = incomingDataSimple;
    /* Set handler private data */
    handler->data = mprAllocTypeZeroed(handler, SimpleData);
    return 0;
}

Creating a Filter

Creating a filter is very similar to creating a handler. An MaStage object is created and initialized.

To create an Appweb filter, you need to call maCreateFilter and supply a unique filter name and flags that modify the behavior of the filter.

The following demonstrates the creation of a "compress" filter.

int maOpenCompressFilter(MaHttp *http)
{
    MaStage     *filter;
    filter = maCreateFilter(http, "compressFilter", MA_STAGE_ALL);
    if (filter == 0) {
        return MPR_ERR_CANT_CREATE;
    }
    /* Define function callbacks */
    filter->outgoingData = outgoingData;
    filter->incomingData = incomingData;
    return 0;
}

Creating a Connector

Creating a connector is similar to creating a handler. An MaStage object is created and initialized.

To create an Appweb connector, you need to call maCreateConnector and supply a unique connector name and flags that modify the behavior of the connector.

The following demonstrates the creation of a "turbo" connector.

int maOpenTurboConnector(MaHttp *http)
{
    MaStage     *connector;
    connector = maCreateConnector(http, "turboConnector", MA_STAGE_ALL);
    if (connector == 0) {
        return MPR_ERR_CANT_CREATE;
    }
    /* Define function callbacks */
    connector->outgoingData = outgoingData;
    connector->incomingData = incomingData;
    return 0;
}

Pipeline Stages Callbacks

Pipeline stages can optionally provide callback functions which are run at various stages of the HTTP request processing. If they are not provided, a default implementation is used.

parse

This callback is invoked to parse configuration directives that may be relevant to the stage. It is called at Appweb startup.

match

This callback is invoked to test if the current request should be serviced by the stage. It is invoked after the request headers are parsed by the Appweb core and before running the request pipeline. If the callback returns false, the stage is removed from the pipeline.

open

This callback is invoked to give the stage a chance to initialize for a given request and potentially allocate any request specific data or state. It is called at the start of request processing after the "match" callback.

incomingData

This callback is invoked to receive any incoming client data (typically POST or PUT data). It is is called after the "open" callback and before the "run" callback.

run

The run callback is invoked to render the response to the client. It is called after processing all input client data.

outgoingData

The outgoingData callback is never called for handlers. Handlers generate data and send it downstream. Filters and connectors will have their outgoingData callback invoked to receive data from upstream. The outgoingData callback will be invoked after the "run" callback has been called for the handler.

close

The "close" callback is invoked to give stages an opportunity to release any request specific data. It is invoked just prior to dismantling the request pipeline.

Stage Data

Stages can allocate stage data and store it in the stage->data field. If the stage needs to store per-request data, it can store it in the stage's queue->data field which is unique for each request.

Stage flags

The create handler, filter and connector APIs take a flags word which modified the behavior of the stage. The flags can take the following values OR'd together

Flag Description
MA_STAGE_ALL All the HTTP methods are suppported.
MA_STAGE_DELETE The stage supports the HTTP DELETE method.
MA_STAGE_ENV_VARS The handler requires a CGI style request environment.
MA_STAGE_FORM_VARS The handler requires query and form data to be stored in the request environment.
MA_STAGE_GET The stage supports the HTTP GET method.
MA_STAGE_HEAD The stage supports the HTTP HEAD method.
MA_STAGE_OPTIONS The stage supports the HTTP OPTIONS method.
MA_STAGE_PATH_INFO The handler requires PATH_INFO processing. The CGI handler is the primary user.
MA_STAGE_POST The stage supports the HTTP POST method.
MA_STAGE_PUT The stage supports the HTTP PUT method.
MA_STAGE_TRACE The stage supports the HTTP TRACE method.
MA_STAGE_VIRTUAL URLs don't map directly onto physical storage for this handler.

Packaging as a Module

Stages are usually delivered as loadable modules. In this manner, users can decide for themselves if the functionality provided by the stage is needed or not. Stages can also be statically linked. See the Creating Modules for more information about how to create a module.

© Embedthis Software LLC, 2003-2012. All rights reserved. Embedthis, Ejscript and Appweb are trademarks of Embedthis Software LLC.