HTTP Server Custom Handler

How to create your custom server (dynamic server, streaming server...) ?

You may wish to create your custom request handler. Here is how it's done.

Handler class Structure

class SimpleHandler : public HTTPRequestHandler
{
public:
  SimpleHandler(const char* rootPath, const char* path, TCPSocket* pTcpSocket);
  virtual ~SimpleHandler();

protected:
  static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTcpSocket) { return new SimpleHandler(rootPath, path, pTcpSocket); } 

  virtual void doGet();
  virtual void doPost();
  virtual void doHead();
  
  virtual void onReadable(); //Data has been read
  virtual void onWriteable(); //Data has been written & buf is free
  virtual void onClose(); //Connection is closing
};

This is the SimpleHandler class header. As you can see, there are a few functions inherited from HTTPRequestHandler that you have to implement.

You must provide a static inst() method which returns a new instance of this class so that the dispatcher can instanciate your handler dynamically.

How does it work?

This handler is event based, so here is how it is going to work:

When a request is dispatched to your handler, the headers are read and stored in the reqHeaders() dictionary. You can access any of these headers like that :

string type = reqHeaders()["Content-Type"];

You can also get the body data length, the path of the request or the constant root path that leads to your handler:

int len = dataLen();
string path = path();
string rootPath = rootPath();

The doXxx() method is called accordingly to the request (e.g. doGet(), doPost() or doHead()).

At this stage there might be some data to be read. Use the readData() function:

int readData(char* buf, int len); //Returns number of bytes read

Should more data be read afterwards, the onReadable() function would be called.

You can send your response using the writeData() function. Before that, be sure that you have set all your response headers information, with the respHeaders() accessor:

respHeaders()["Connection"] = "close";

You can also set the body data length with the setContentLen() function. Should you return an error code different than 200, be sure to set it as well.

setContentLen(100);
setErrCode(404);

int writeData(const char* buf, int len); //Returns number of bytes written

When a packet has been sent an you can write more data, the onWriteable() function is called.

If the remote host closes the connection or on timeout, the onClose() function is called. If you want to close the connection yourself, use the close() function.

Examples

Be sure to check the existing implementations, from the basic SimpleHandler to the more advanced RpcHandler and FSHandler.


All wikipages