|
From: Dean M. B. <mik...@gm...> - 2010-02-11 17:27:50
|
Hey Darren!
It's great to see you here. :)
On Fri, Feb 12, 2010 at 1:02 AM, Darren Garvey <dar...@gm...> wrote:
>
> On 11 February 2010 14:25, Dean Michael Berris <mik...@gm...>
> wrote:
>>
>> I was thinking about this a little and thought it would be cool to
>> have a collection of utilities of commonly-performed actions that
>> others might find useful in the library. Off the top of my head I find
>> that these would be cool functions/mini-libraries to have:
>>
>> * MIME Parser (Marshall Clow has a cool one worthy of more attention
>> and discussion, hopefully he merges it into cpp-netlib in time for
>> BoostCon 2010 ;) ).
>
> I've taken a look at this. It looks pretty cool, like it could fit the bill.
> Two extra features that I would find very useful are:
>
> * Either:
> - Ability to restart the parser - ie. support chunked data.
> or:
> - Ability to pass in a Boost.Asio-compatible *ReadStream instead of an
> istream.
> * Ability to store file uploads directly to the filesystem (ie. so you can
> support uploading huge files).
>
I think Marshall has taken the input from the boost-devel mailing list
regarding this and *might* be working on something similar. I'm not
sure though what his timetable on that would be. :)
> Marshall, are you planning to integrate your MIME parser with cpp-netlib?
>
/me silently wishes Marshall does! :D
>> * Form encoding/decoding (for HTTP clients/servers to handle HTML
>> form encoded data)
>> * Query string encoding/decoding (for GET queries)
>> * Base64 stream/string encoding/decoding (for Binary data)
>
> There is overlap with the CGI library under development. Is there anything
> we can do to find some common ground here?
>
Definitely!
Have you looked at the HTTP Server template yet? It's very bare and if
we can plug in the CGI handlers through the HTTP Server template then
I think my search for one half of a C++ Application Servlet Container
would be complete. The other half would only be actual session
handling and persistence subsystem managers. :D
>>
>> * URI pattern-based dispatch (ala Rails, or Django/Tornado)
>
> Very useful feature, but must be kept distinctly separate from the core
> IMHO.
100% agree. I'm thinking this alone would be cool in its own right and
might be a full-blown library waiting to happen. I can definitely see
this being useful in other contexts like command consoles, scripting
interfaces, etc. -- which is also why I'm thinking a utilities
collection would be a good place to host something like this. ;)
> I have some code which does dynamic dispatching of handlers based on
> regular expressions matching with the path-info of a request. This also
> dispatches to a specific handler depending on the request-method of the
> request. For example:
>
> // One of many potential request handlers:
> struct some_handler : request_handler<some_handler, Context>
> {
> int get(Context& self) { /* ... */ }
> int post(Context& self, boost::regex_match& url_matches) { /* ... */ }
> int put(Context& self) { /* ... */ }
> };
>
> The above pattern uses virtual functions to allow it to work. When a handler
> for the specified request method isn't found, this is captured in the base
> class. If the handler overrides the base class method, the handler's method
> is called. The handler is able to have an optional regex_match argument,
> which allows the regular expression of the match to use sub-matches.
>
> For example, the url pattern "(/*)" would match any request and attempt to
> call the relevant handler. If the handler took a regex_match, this would be
> called with the full path_info of the request.
>
This sounds like exactly what I'm looking for. My only gripe is that
it uses virtual functions. ;)
> The code doesn't currently fall back to a handler that works with any
> request method, but could easily enough. Also, it may benefit from some
> metaprogramming to make the dispatching static... My feelings at the time
> were that one or two virtual function calls per request are fine - feel free
> to disagree!
>
Actually, I think you can get away with a chain pattern, using
Boost.Fusion for compile-time wired static dispatch. If I understand
it correctly, you might be able to get away with a combination of
Boost.Xpressive for the statically defined regex's and handlers that
adhere to a certain Concept.
The recipe would involve (from the top of my head) a Fusion sequence
of pairs of Xpressive patterns and opaque handlers. You run it through
Fusion's `any` function and find the first match and invoke the
associated handler. Given a little more prodding I might implement it
myself just as an exercise on Fusion, Xpressive, and some
metaprogramming kung fu. :)
>
>>
>> I find myself wanting to write these myself or at least using them
>> when I write programs that use cpp-netlib. Simple things like for HTTP
>> server based applications I want to be able to parse a list of
>> parameters (remembering what Jeroen was proposing to do with the URI
>> parser one time).
>>
>> Any takers? It would be cool if we had these in the library before May
>> where I will be presenting the library and the techniques used in the
>> library at a high level. ;)
>
> Not sure how much time I'll have to spare as I'm quite busy with work and
> pushing to getting a release of the CGI library out ASAP. I use
> Boost.Tokenizer for splitting query strings and cookies and a custom
> url_decode function for parsing. The data is stored in std::map<>s, with a
> case-insensitive string as the key_type.
>
> That said, these aren't using Spirit yet. Maybe compilers are fast enough to
> deal with sprinklings of Spirit coolness everywhere now?
>
Boost.Spirit FTW -- the cost of compile times definitely justify the
performance gains at runtime. :)
> Cheers,
> Darren
>
Thanks for sharing your thoughts Darren! I hope some of my thoughts help too. :D
I'm also looking forward to the CGI library. :)
--
Dean Michael Berris
cplusplus-soup.com | twitter.com/deanberris
linkedin.com/in/mikhailberis | facebook.com/dean.berris | deanberris.com
|