On Sun, Feb 21, 2010 at 5:28 PM, Tai Lee <real.hu...@mrmachine.net> wrote:
> On Feb 21, 7:46 am, Forest Bond <for...@alittletooquiet.net> wrote:
>> Okay, I think "disabled_middleware" is a bad name because it doesn't actually
>> imply that all middleware should be disabled.  Anyway, it seems like 
>> middleware
>> could just check if isinstance(response, StreamingHttpResponse).
>
> I'm not sure I follow your reasoning here. If you just don't like the
> name, that's a bike shed argument. I'm proposing that
> `disabled_middleware` be a list or tuple of middleware that should NOT
> be called on the response, because the author of the `HttpResponse`
> subclass that defined `disabled_middleware` knows that those
> middleware are not needed or will not work as intended.
>
> The point that I gleaned from earlier discussions is that we cannot
> fix this problem in middleware. We cannot have middleware check `if
> isinstance(response, StreamingHttpResponse)` and conditionally change
> its behaviour because we would force ALL Django and 3rd party
> middleware in existence to check for the possibility that a response
> has generator or string content and change their behaviour
> accordingly.

Any existing middleware that tries to evaluate response.content will
be draining iterator-based content at present, which will be breaking
responses. If a middleware is currently buggy, providing an API for
developers to make their middlewares not buggy is certainly a viable
option.

That said, a straight up "isinstance" call probably isn't the best
option - more on this in a bit.

> I believe the answer is to define explicit `HttpResponse` subclasses
> and provide a mechanism by which each subclass can explicitly disable
> certain middleware. That way, all existing Django and 3rd party
> middleware do not need to change or know or care about what kind of
> content the response has. Then the developer can simply disable any
> middleware that is causing a problem with a particular response,
> regardless if it is a problem with streaming, or they don't want an
> ETag, or they don't want a response compressed, etc.

The problem with this approach is that it doesn't work well with a
fully reusable stack. If I build an app with the intention of re-use,
I don't know the middleware stack that will exist when my app is
deployed.

If I manually exclude an ETag middleware, there's no guarantee that
middleware will be used. This isn't inherently a problem - we could
just document that any middlware named for exclusion that isn't in use
will be ignored.

However, the converse situation does cause problems. If the developer
using my app has written a custom middleware than tries to twiddle the
content of the response, I won't know the name of that middleware in
advance to put it on a ban list.

To me, it seems like what we need to be able to capture in a response
object is the set of capabilities that a response supports -- For
example:

 * Can I determine the length of this response?
 * Can I inspect the contents of this response?
 * Can I modify the contents of this response?

In the case of a simple static HTTP response, the answer is "yes" to all three.

In the case of Simon Willison's proposed TemplateResponse (see ticket
#12815), the answer to both is maybe, depending on the whether the
template has been baked yet (and there might be certain conditions
under which you might want a length/content request to induce baking)

In Forest's "streaming from Cloudfiles" use case, we can provide the
length of the response; we can't inspect or twiddle the content.

Tai's use case can't provide a length, but will allow content
modification (to provide a GZipped stream, for example)

These capabilities are just a starting point. Defining these
capabilities will be an important design process. It would be easy to
just add "Has a known ETag?" and "Can be cached?" as capabilities, but
we may need to look deeper to see if these questions are really asking
something more significant.

I'm not sure the Etag question has anything deeper behind it, but the
caching restriction really has more to do with whether we can know in
advance whether the content will be large, or whether the entire
response can (or should) be loaded into memory at once. Regardless of
the final form -- it's the deeper concepts that need to be captured as
capabilities.

What I'm driving at here is getting to the core of duck typing. As the
developer of FooMiddleware, I don't really care whether I get a
HttpResponse, a StreamingHTTPResponse, or something else entirely --
what I care about is whether I can iterate over the content, modify
the content, ask for a content length, or whatever it is that my
middleware needs to do. The capabilities is more important than the
specific type -- especially when the capabilities are subject to
change (such as Forrest's example where Etags and content lengths can
be provided, as long as GZipping is disabled).

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-develop...@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to