Sorry for the late answer. On Sun, Jun 06, 2010 at 11:33:20PM +0100, Enrico Zini wrote: > Bottle seems to be extracting the first element from the iterable in > order to look at what the iterator returns and possibly add transparent > recoding and whatnot, then it returns a chain iterator with the first > element it took out and the rest. > > Now, the WSGI server, even if it supports the file_wrapper > optimisation[1], will never be able to see that we are returning a > file_wrapper, so the optimisation will never trigger, in the face of > what Bottle's documentation says. > > The same also defeats the idea that in WSGI, if you return an object > that has a close() method, it will be called at the end of the request. > In this case, Bottle will wrap our returned generator (which has a close > method) in one that doesn't. > > Goodbye cleanup after streaming ends.
Fixed in 590f213238d7b65eabc53fd5f7c47375b02a075e > So, much more simple and readable, and with only one environ lookup: > > # Cast Files into iterables > if hasattr(out, 'read'): > wrapper = request.environ.get('wsgi.file_wrapper', None) > if wrapper: out = wrapper(out) > return out The 'wsgi.file_wrapper' is optional and we must return an iterable. Some file-like objects may not be iterable. A working fallback won't hurt :) -- Mit freundlichen Grüßen Marcel Hellkamp
>From 590f213238d7b65eabc53fd5f7c47375b02a075e Mon Sep 17 00:00:00 2001 From: Marcel Hellkamp <m...@gsites.de> Date: Fri, 18 Jun 2010 23:53:19 +0200 Subject: [PATCH] fix: Return wsgi.file_wrapper wrapped files directly to the wsgi server. Thanks to Alex Popescu, Enrico Zini and David Paleino. --- bottle.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bottle.py b/bottle.py index fef1837..e968bdd 100755 --- a/bottle.py +++ b/bottle.py @@ -508,8 +508,8 @@ class Bottle(object): # File-like objects. Wrap or transfer in chunks that fit into memory. if hasattr(out, 'read'): - out = request.environ.get('wsgi.file_wrapper', - lambda x, y: iter(lambda: x.read(y), tob('')))(out, 1024*64) + return request.environ.get('wsgi.file_wrapper', + lambda x: iter(lambda: x.read(1024*64), tob('')))(out) # Handle Iterables. We peek into them to detect their inner type. try: -- 1.7.0.4