26 Aug 2007

More fun with HTTP...

I pretty much finished the HttpServer stuff over the weekend. All in all it took me about 10 hours of work (I don't even want to imagine how long it would have taken in Nebula2, probably a week or even longer, and the result wouldn't look half as elegant). The HttpServer is a singleton with a TcpServer inside, and a number of attached HttpRequestHandlers. A HttpRequestHandler is a user-derivable class which processes an http request (decoded by a HttpRequestReader) and produces a content stream (usually an HTML page) which is wrapped into a HttpResponseWriter object and sent back to a web browser. HttpRequestHandlers may accept or reject a http request. When a new request comes in from a web browser, the HttpServer asks each HttpRequestHandler in turn whether it wants to handle the request. The first handler that accepts will process the request. If no attached request handler accepts, the "default handler" has to produce a valid response (the default handler usually serves the "home page" of the Nebula3 application).

To simplify producing valid HTML pages, I wrote a HtmlPageWriter. This is a subclass of StreamWriter and has an interface which allows to insert HTML elements and text into the stream. All basic HTML markup elements up to tables are supported, so a HttpRequestHandler can do pretty advanced stuff if it wants to.

Here's how it works from the outside:

When a Nebula3 application is running (should be derived from App::RenderApplication, this sets up everything automatically), start a web browser on the same machine, and type the address http://127.0.0.1:2100 into the address field. This opens a HTTP connection on the local machine on port 2100 (it's also possible of course to do this from another machine as long as the port 2100 isn't blocked).

The browser should now display something like this:


This is basically the debug home page of the application. At the top there's some basic info like the company and application name that have been set in the Application object. The calendar time displays what the application thinks the current time is. It will update when hitting F5 in the browser.

The Available Pages section lists all attached HttpRequestHandler objects. By deriving new classes from HttpRequestHandler and attaching an instance to the HttpServer singleton the Available Pages list will grow automatically.

To go to the application's Display debug page, either click on the link, or type http://127.0.0.1:2100/display into the browser's address bar. This should bring up the following page:

The Display page lists the properties of the currently open display, and some information about the display adapters in the system.

But there's also more powerful stuff possible. The IO page lists (among other things) all currently defined assigns, and how they resolve into file system paths. The IO page can be reached through the URI http://127.0.0.1:2100/inout. However, the request handler that builds the IO debug page also has a complete directory lister integrated, so one can check what files the application actually can see under its assigns. Typing http://127.0.0.1:2100/inout?ls=home: into the browser's address field produces this page:


You can actually click on subdirectories and navigate through the entire directory structure. This is all basic stuff which I wrote in the last 3 hours (in the ICE train to Berlin), so it's really simple and fast to get results from the HttpServer system. The one thing that's missing now is a Base64Writer so that it would be possible to send binary data over the line (especially image data), and of course a few more HttpRequestHandlers which expose more debug information to the web browser.