Graham Fawcett wrote:
> I've been writing a Quixote app in a somewhat RESTful style, that needs
> to do content negotiation on certain requests. By 'content negotation',
> I mean that I need to examine the Accept header in the request, and
> return an appropriate response in one of the MIME types declared there.
I'm also designing an application in REST style using Quixote. I don't
have any criticisms of your solution, but I'd like to make a few
observations.
> A recurrent pattern was cropping up in my code:
>
> def _q_index(req):
> acceptlist = req.environ['HTTP_ACCEPT'].split(',')
> if 'text/html' in acceptlist:
> # return a text/html representation
> elif 'text/xml' in acceptlist:
> # return a text/xml representation
> ...
There is no need for this. See
quixote.http_request.HTTPRequest.get_accepted_types.
> def text_html [html] (cls, req):
> some_header(req)
> 'An HTML response!
'
> some_footer(req)
>
> def text_xml [html] (cls, req):
> ''
>
> def text_ [plain] (cls, req):
> 'A response to text/* requests'
I'd guess that in many designs, XML is the "source" format, with HTML
and plain text being generated by transforming the XML. So to me, this
can all be automated even more, and doesn't warrant splitting into
separate handlers.
> Back to acceptfunction. A similar approach could be used to make
> 'function classes' for functions that need to dispatch based on method
> (GET, PUT, ...), user agent, locale, etc. (Though I dread to think about
> having to write a _q_index.text_html.put.en_us() function and its
> hundred-odd companions!)
In my design, I decided that making handlers according to HTTP method
was most important. Instead of using a meta class (which I know little
of) to implement this, I simply made a base class that scanned its
function attributes in __init__. A nice side effect was being able to
automatically generate a Method Not Allowed response with appropriate
Allowed header (assuming the list of accepted methods is static).
Regards,
-John
--
http:// if le.o /