An HTTP "rules engine".
I'm seriously contemplating the creation of yet another web server... actually, this isn't entirely true. What I really want to do is make it easy to connect a few components together in lua so that anyone can create the web server of their choice. Today it is pretty easy to use lua-ev in combination with luasocket and lua-http-parser in order to write a web server. However, lua-ev is still a little rough around the edges. In particular, I would like to do these improvements when time allows it:
- Support for coroutines so that the event loop can implement "green threads".
- Support for "error backs" so that an event loop callback that throws an error can recover from that error (like send a 400 bad request back to the client if there is an error during HTTP parsing, or an error happens in the content handler such that we need to create a 500 internal server error).
- Support the "proactor" design pattern such that it is trivial to register a callback that will be ran with the results of a read operation (and if the read fails or if a time limit is exceeded, the "error back" chain would be ran with an appropriate error message).
However, the biggest missing piece in my mind is a way to enable people to "plug-in" to your web server. In essence, what I really need is an HTTP rules engine. For example, Apache mod_rewrite is really just a rules engine that toggles various pieces of the request object based on some regular expressions. What if this idea was extended so that the response can also be manipulated, and that you could have rules that depend on other rules? This rules engine could then be the primary point of extension for people that want to write "plug-in"s.
An HTTP Rules Engine
At a high level, the rules engine API allows you to define a set of rules that runs arbitrary lua code which can modify the "request object" or "response object". The rule can be triggered by request or response meta-data, and rules can define a set of dependencies (only run this rule if these other rules have already been ran). All incoming requests are pumped into the rules engine which then triggers a bunch of arbitrary lua code to be called which then assembles the response. To prevent infinite loops, a rule can only be executed N times per request-response cycle (where N is configurable, and this failure is non-fatal, but is logged).
The "request object" consists of: the request method, the requested url, the query string, the HTTP version, the http headers, the "cookies", the remote ip, and the input filter chain. The input filter chain allows anybody to register a lua function to filter the incoming request body through a function or to register one or more input handlers. If no input handler is registered, the request body is simply ignored. Once the input filter chain is put to use on the body of the request, the filter chain is immutable (any attempt to change it cause errors).
The "response object" consists of: the HTTP version, status code, reason phrase, http headers, and the output filter chain. The output filter chain allows anybody to register a lua function to filter the outbound response body through a function or to reserve one or more "chunks" of output (where the response meta-data represents the first chunk of output).
The "reservation system" makes it possible to generate the response while making parallel service calls to the back-end. For example, you can write a rule to generate a footer by reserving the last chunk, then immediately "emitting" the footer. Yet the body of the response can still be generated by another rule that reserves the "next chunk", and may depend on some back-end service call results. This reservation system also allows for AJAX push notifications.
So, what do you think of this HTTP "rules engine"? Do you think this API is complete? Are you wishing this API already existed?
