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.
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);
}
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.
Creating 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.