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.