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.