Creating AppWeb URL Handlers

Mbedthis AppWeb supports extension handlers that can process any kind of HTTP content. The core AppWeb HTTP server cannot serve any pages or documents by itself. It relies on URL handlers delivered as modules to actually serve HTTP requests. AppWeb is itself comprised of 7 different handlers which serve all the content provided by an AppWeb server. 

This document describes the AppWeb URL Handler Interface and how to create AppWeb handlers. Handlers are usually delivered as stand-alone loadable modules. In this manner, users can decide for themselves if the functionality provided by the handler is needed or not. But the AppWeb Module interface is only a delivery option. Handlers can be statically linked and do not rely on the module mechanism to operate.

See also how to configure handlers and the simpleHandler sample for sample code implementing a simple Handler.

top Overview

To create an AppWeb handler,  you need to create an instance of a subclass of the MaHandlerService class and insert the instance into the Http service. This MaHandlerService class is the factory to create instances of your actual handler in response to incoming HTTP client requests. When a new HTTP request arrives, the newHandler method is called for the factory class to create a new MaHandler instance to process the request.

If the handler is being packages as an AppWeb Module, it is often most convenient to create a new instance of the MaHandlerService class in the Module constructor.

top HandlerService

The class definition for an AppWeb Handler is described below. Note the start and stop methods are optional.

class MyHandlerService : public MaHandlerService {
public:
MyHandlerService();
~MyHandlerService();
MaHandler *newHandler(MaServer *server, MaHost *host, char *ext);
int start();
int stop();
};

The follow code demonstrates an AppWeb Module constructor that creates the handler service and inserts it into the applications Http service. Note that while AppWeb Handler services are global to the application, you can specify on a per server or virtual host basis whether the handler is active or not vi AppWeb configuration file directives.

MyHandlerModule::MyHandlerModule(void *handle) : MaModule("MyHandler", handle)
{
mprLog(0, "In MyHandlerModule()\n");

//
// Create the handler service (one per application) and insert into
// the HTTP service.
//
myHandlerService = new MyHandlerService();
maGetHttp()->insertHandlerService(myHandlerService);
}

top Handler Class

Once the MaHandlerService instance is created it will be instances of the MaHandler class that will run actually service the HTTP client requests. The following is the class definition for our MyHandler class.

class MyHandler : public MaHandler {
public:
MyHandler(char *extensions);
~MyHandler();
MaHandler *cloneHandler();
int matchRequest(MaRequest *rq, char *uri, int uriLen);
void postData(MaRequest *rq, char *buf, int buflen);
int run(MaRequest *rq);
int setup(MaRequest *rq);
};

The MaHandler class can optionally provide several methods which are run a various stages of the HTTP request processing. The matchRequest method is run to determine if the handler should be called to examine or process the request. If the handler matchRequest method returns TRUE, the run method will be called later to process the request. After matching the request, the setup method is called to allow the handler to do any required initialization.

For maximum speed, the cloneHandler method is provided to allow the quick creating of new handler instances of the same configuration as the curren thandler instance.

The postData method is called (may be prior to the run method), to process any incoming POST data. It is up to the handler to decide what to do with the data. The run method is called to actually process the request. If the handler is a terminal handler, then it is responsible for returning the resulting data back to the client's browser. If the handler is a non-terminal handler, then it must either abort the request by calling rq->requestError or it should zero to allow other handlers to process the request.

topCreating Handlers

A handler specifies whether it is terminal or non-terminal when it is constructed. The constructor for MaHandler takes an options flag that can take the following values:

Flag
Description
MPR_HANDLER_DELETE
The handler supports the HTTP DELETE method.
MPR_HANDLER_GET
The handler supports the HTTP GET method.
MPR_HANDLER_HEAD
The handler supports the HTTP HEAD method.
MPR_HANDLER_OPTIONS
The handler supports the HTTP OPTIONS method.
MPR_HANDLER_POST
The handler supports the HTTP POST method.
MPR_HANDLER_PUT
The handler supports the HTTP PUT method.
MPR_HANDLER_TRACE
The handler supports the HTTP TRACE method.
MPR_HANDLER_NEEDS_ENV
The handler want to have a hashed symbol table created with CGI style variables defined.
MPR_HANDLER_ALWAYS
The handler always matches incoming requests and does not call the matchRequest method.
MPR_HANDLER_MAP_VIRTUAL
Don't map the URL onto physical storage.
MPR_HANDLER_ALL
All the above


For example, the following code fragment will configure a handler to be a terminal handler supporting the GET and POST methods.

                                
MyHandler::MyHandler(char *extensions) : MaHandler("MyHandler", extensions,
MPR_HANDLER_GET | MPR_HANDLER_POST | MPR_HANDLER_NEED_ENV | MPR_HANDLER_TERMINAL)
{
// Code here
}


The Handler sample and the handlers provided in the AppWeb source code demonstrate many other variations on how to create and use handlers.


© Mbedthis Software LLC, 2003-2204. All rights reserved. Mbedthis is a trademark of Mbedthis Software LLC.