Boost logo

Boost :

From: Darren Garvey (lists.drrngrvy_at_[hidden])
Date: 2007-04-22 01:43:06


Hi Steven, sorry about the late reply (I've been travelling).

On 07/04/07, Steven Siloti < ssiloti_at_[hidden] > wrote:
>
> I've been working on a library for writing web applications (via any
> sort of gateway: cgi, fcgi, scgi, mod_proxy_http, etc.) that might be of
> interest here. This is all very preliminary as it's something I hack on
> in my spare time more-or-less as an exercise (I don't even have much of
> a use for such a library!).
>
> It's design is inspired by Python's WSGI in that you build up a context
> based on a stack of middleware classes which act as mixins to provide
> abstractions and services on top of a base request/response provided by
> the gateway.

I've looked at WSGI in the past for ideas, so I'm vaguely familiar with it.
I'm taking a proper look at it now. If you'd be willing to discuss your
approach more (by private email if you prefer), I'd love to share ideas.

The mixin system I've created allows mixins to make arbitrary
> additions/changes to the context structure. At the core is a stack class
> which handles combining multiple mixins into a single (potential)
> context. Here what it looks like right now:
>
> http://magila.googlepages.com/context.hpp
>
> It's actual method of operation is somewhat involved. Basically each
> mixin consists of three types: a constructor object, a context
> definition structure, and context instance structure. The constructor
> object is the mixin class itself, it's responsible for carrying any
> initialization parameters to the final instance.
>
> Inside the mixin class a context definition structure (ctx_type) and a
> context instance structure (type) are defined. The idea is to first
> build up a type which defines the final structure of the context then
> pass that as a template parameter to the instance type which actually
> instantiates the various structures contained therein. The two step
> process is necessary because otherwise you get a loop were a derived
> class's type depends on it's base who's type depends on the derived
> class's type.
>
> Here's an example of a basic http context and a simple mixin which
> parses the Content-Length header out as an int and provides an int in
> the response which is assigned to the response's Content-Length header.
>
> http://magila.googlepages.com/http_context.hpp
> http://magila.googlepages.com/http_mixins.hpp
>
> These can be combined using the stack class as such:
>
> stack<http::context, http::content_length>
>
> The result is a type which is itself a valid mixin. This allows a lot of
> flexibility in how you build up a context. Once you've built up you
> context with all the middleware you want you pass it as a template
> parameter to a gateway class which is responsible for adding it's own
> base request/response part of the context then calling process_request()
> to kick off the upper layers in the stack.
>
> To hide all this complexity from the end user we use a resource mixin
> which takes a class as a template parameter and calls an appropriate
> member function based on the http method in the request and passes it a
> reference to itself. See:
>
> http://magila.googlepages.com/http_resource.hpp
>
> And finally a trivial example of how it all looks to the end user:
>
> http://magila.googlepages.com/swgl_test.cpp

The library sounds quite industrial (which is possibly a good thing, IMO),
but this example _looks_ industrial. Is this really the simplest case?
Also, if I'd written a large program using this framework, is there a simple
path to make the same program work with a different protocol?

You'll note I've left out the gateway class. What I'm using now is just
> a trivial standalone server using asio that I wrote just for debugging
> that's not in any shape that I'd want to show :).

I've had a look at the gateway class (at least the one on the server,
sorry). I'm surprised you didn't show it too, as I think it makes the rest
of your code much more understandable. :)

As an example, to create an instance of the final context you would do
> something like this:
>
> stack<base_context, upper_context>::type<> ctx(base_context(req, res),
> upper_context(foo, bar, bas));
>
> And thus each mixin's ::type's constructor would be passed an object
> inheriting from it's containing class and which has been constructed
> from the instance of that class passed to the stack's constructor.

It's an interesting idea and the syntax is somewhat appealing too. I'm not
sure how necessary it is for a 'from scratch' approach though... How close
is this to Python's WSGI (if that's a reasonable question)?

Needless to say the code here is all very much a WIP and only provided
> for reference. Sorry if this has all been a waste of (your) time, just
> thought I'd throw it out there.

Not at all. I'm glad you did.

Cheers,
Darren


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk