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 |