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 terminalhandler, 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.