librelist archives

« back to archive

Flask API design / absence of global response objects

Flask API design / absence of global response objects

From:
Martín Blech
Date:
2012-11-15 @ 18:45
I am wondering why in Flask there is no global response object. Flask uses
this approach for requests, and frameworks such as Bottle, webapp2 and
web.py use it for both requests and responses.

Why did Flask take the
build-your-own-response-object-or-return-a-string-or-a-pair-or-a-tuple
road? The other approach seems a bit more elegant. Can someone comment on
this?

Re: [flask] Flask API design / absence of global response objects

From:
Calvin Young
Date:
2012-11-15 @ 19:06
+1 I'd love to hear more about this as well.

The current API makes it difficult to perform operations such as setting a
cookie or modifying a response header when it doesn't make sense to have
built a response object yet (the recommended workaround is to use deferred
request 
callbacks<http://flask.pocoo.org/docs/patterns/deferredcallbacks/#deferred-callbacks>).
 A global response object would make these operations much simpler and more
intuitive.

On Thu, Nov 15, 2012 at 10:45 AM, Martín Blech <martinblech@gmail.com>wrote:

> I am wondering why in Flask there is no global response object. Flask uses
> this approach for requests, and frameworks such as Bottle, webapp2 and
> web.py use it for both requests and responses.
>
> Why did Flask take the
> build-your-own-response-object-or-return-a-string-or-a-pair-or-a-tuple
> road? The other approach seems a bit more elegant. Can someone comment on
> this?
>

Re: [flask] Flask API design / absence of global response objects

From:
Mark Grey
Date:
2012-11-15 @ 19:02
The only framework I have worked with in the past that utilized one global
response object is Kohana3 in PHP, so I don't claim any advanced knowledge.

My impression is that the request object is essentially intended to be
immutable; this is reflected in the manner in which the request.values,
request.form, request.args and request.values are all ImmutableDict types.
 It makes empirical sense since one line of execution will answer one
request.

The response to be returned however is only relevant in the final part of
processing, which may be a full textual/html response in the case of
success, or may be returned much sooner in the case of an error or
exception.  I guess the case I have in mind is an error : the endpt will
invariably capture the exception and return immediately, perhaps with a
flag indicating failure and an string explanation, in which case generating
a response within the except block and returning it immediately makes good
sense.  One must wonder if this would be improved by having a global
request object into which the error data is pushed or updated.  I think
since the error cases almost all immediately return their responses, the
idea of generating it right at that moment rather than updating
a preexisting one would make the most sense.  After all, what would the
prepopulated data contain, just an empty body?

The nature of python as a EAFP language seems predisposed to generating the
final message right when the execution has completed, be it in error or
success.

On Thu, Nov 15, 2012 at 1:45 PM, Martín Blech <martinblech@gmail.com> wrote:

> I am wondering why in Flask there is no global response object. Flask uses
> this approach for requests, and frameworks such as Bottle, webapp2 and
> web.py use it for both requests and responses.
>
> Why did Flask take the
> build-your-own-response-object-or-return-a-string-or-a-pair-or-a-tuple
> road? The other approach seems a bit more elegant. Can someone comment on
> this?
>

Re: [flask] Flask API design / absence of global response objects

From:
Martín Blech
Date:
2012-11-15 @ 19:48
The two approaches that I am trying to compare are:

A. handler functions in global request + global reponse
(Bottle/webapp2/web.py):

   - *request headers/cookies/etc.*: get them from the global request object
   - *response headers/cookies/etc.*: put them on the global response object
   - *in*: URL match groups
   - *out*: contents

B. handler functions in Flask:

   - *request headers/cookies/etc.*: get them from the global request object
   - *in*: URL match groups
   - *out*: either the contents, or a (contents, status) tuple, or a
   (contents, status, headers) tuple, or a response object you built yourself
   and populated with cookies and whatnot.


I think approach A is much cleaner, since there is less variability in what
you can return from your handler function. It's also more elegant, as there
is symmetry on how you handle headers and cookies for both requests and
responses. But perhaps approach B has some advantage that I fail to see.

Was approach A ever considered? Why was B chosen instead?

As the maintainer of a library that tries to support all the mentioned
frameworks, this mismatch is a bit painful.


On Thu, Nov 15, 2012 at 4:02 PM, Mark Grey <mark.asperia@gmail.com> wrote:

> The only framework I have worked with in the past that utilized one global
> response object is Kohana3 in PHP, so I don't claim any advanced knowledge.
>
> My impression is that the request object is essentially intended to be
> immutable; this is reflected in the manner in which the request.values,
> request.form, request.args and request.values are all ImmutableDict types.
>  It makes empirical sense since one line of execution will answer one
> request.
>
> The response to be returned however is only relevant in the final part of
> processing, which may be a full textual/html response in the case of
> success, or may be returned much sooner in the case of an error or
> exception.  I guess the case I have in mind is an error : the endpt will
> invariably capture the exception and return immediately, perhaps with a
> flag indicating failure and an string explanation, in which case generating
> a response within the except block and returning it immediately makes good
> sense.  One must wonder if this would be improved by having a global
> request object into which the error data is pushed or updated.  I think
> since the error cases almost all immediately return their responses, the
> idea of generating it right at that moment rather than updating
> a preexisting one would make the most sense.  After all, what would the
> prepopulated data contain, just an empty body?
>
> The nature of python as a EAFP language seems predisposed to generating
> the final message right when the execution has completed, be it in error or
> success.
>
>
> On Thu, Nov 15, 2012 at 1:45 PM, Martín Blech <martinblech@gmail.com>wrote:
>
>> I am wondering why in Flask there is no global response object. Flask
>> uses this approach for requests, and frameworks such as Bottle, webapp2 and
>> web.py use it for both requests and responses.
>>
>> Why did Flask take the
>> build-your-own-response-object-or-return-a-string-or-a-pair-or-a-tuple
>> road? The other approach seems a bit more elegant. Can someone comment on
>> this?
>>
>
>

Re: [flask] Flask API design / absence of global response objects

From:
Kenneth Reitz
Date:
2012-11-15 @ 19:49
>>> from flask import Response  

--  
Kenneth Reitz


On Thursday, November 15, 2012 at 7:45 PM, Martín Blech wrote:

> I am wondering why in Flask there is no global response object. Flask 
uses this approach for requests, and frameworks such as Bottle, webapp2 
and web.py (http://web.py) use it for both requests and responses.
>  
> Why did Flask take the 
build-your-own-response-object-or-return-a-string-or-a-pair-or-a-tuple 
road? The other approach seems a bit more elegant. Can someone comment on 
this?  

Re: [flask] Flask API design / absence of global response objects

From:
Mark Grey
Date:
2012-11-15 @ 20:00
We'll I'll be.  Unless I'm mistaken, Kevin is right, the directly imported
Response object is in fact the default Response object from the Werkzeug
layer below:

http://flask.pocoo.org/docs/api/?highlight=response#flask.Response

On Thu, Nov 15, 2012 at 2:49 PM, Kenneth Reitz <me@kennethreitz.com> wrote:

> >>> from flask import Response
>
> --
> Kenneth Reitz
>
> On Thursday, November 15, 2012 at 7:45 PM, Martín Blech wrote:
>
> I am wondering why in Flask there is no global response object. Flask uses
> this approach for requests, and frameworks such as Bottle, webapp2 and
> web.py use it for both requests and responses.
>
> Why did Flask take the
> build-your-own-response-object-or-return-a-string-or-a-pair-or-a-tuple
> road? The other approach seems a bit more elegant. Can someone comment on
> this?
>
>
>

Re: [flask] Flask API design / absence of global response objects

From:
Martín Blech
Date:
2012-11-15 @ 20:08
On Thu, Nov 15, 2012 at 4:49 PM, Kenneth Reitz <me@kennethreitz.com> wrote:

> >>> from flask import Response
>

That statement imports the Response *class*, not a global response *object*.