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.

pipeline

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 maSimpleHandlerInit(Http *http, MprModule *module)
{
    HttpStage   *handler;
    handler = httpCreateHandler("simpleHandler", module);
    if (handler == 0) {
        return MPR_ERR_CANT_CREATE;
    }
    /* Define function callbacks */
    handler->match = matchSimple;
    handler->open = openSimple;
    handler->close = closeSimple;
    handler->start = startSimple;
    handler->writable = writableSimple;
    handler->incoming = incomingSimple;
    handler->outgoing = outgoingSimple;
    handler->incomingService = incomingServiceSimple;
    handler->outgoingService = outgoingServiceSimple;
    /* Set handler private data */
    handler->stageData = mprAllocObj(SimpleData, 0);
    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 maCompressFilterInit(Http *http, MprModule *module)
{
    HttpStage   *filter;
    filter = httpCreateFilter("compressFilter", module);
    if (filter == 0) {
        return MPR_ERR_CANT_CREATE;
    }
    /* Define function callbacks */
    filter->outgoing = outgoing;
    filter->incoming = incoming;
    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 maTurboConnectorInit(Http *http, MprModule *module)
{
    HttpStage   *connector;
    connector = httpCreateConnector("turboConnector", module);
    if (connector == 0) {
        return MPR_ERR_CANT_CREATE;
    }
    /* Define function callbacks */
    connector->outgoing = outgoing;
    connector->incoming = incoming;
    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.

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.

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.

start

The start callback is invoked to start processing the response for the client. If the request is a form with Content-Type of "application/x-www-form-urlencoded", the start callback is called after processing all input client data. Otherwise, it is called before any input data.

ready

The ready callback is invoked once all the request body data has been received.

writable

The writable callback is invoked after receiving all body data and whenever the output pipeline can absorb more data.

incoming

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

outgoing

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

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
HTTP_STAGE_ALL All the HTTP methods are supported.
HTTP_STAGE_DELETE The stage supports the HTTP DELETE method.
HTTP_STAGE_PARAMS The handler requires query and form data to be stored in the request params.
HTTP_STAGE_GET The stage supports the HTTP GET method.
HTTP_STAGE_HEAD The stage supports the HTTP HEAD method.
HTTP_STAGE_OPTIONS The stage supports the HTTP OPTIONS method.
HTTP_STAGE_POST The stage supports the HTTP POST method.
HTTP_STAGE_PUT The stage supports the HTTP PUT method.
HTTP_STAGE_TRACE The stage supports the HTTP TRACE method.

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 section for more information about how to create a module.

© Embedthis Software. All rights reserved.