#29069: Static file serving does not call request_finished signal
-------------------------------------+-------------------------------------
Reporter: André Cruz | Owner: nobody
Type: Bug | Status: new
Component: HTTP handling | Version: 1.11
Severity: Normal | Resolution:
Keywords: streamingresponse | Triage Stage: Accepted
request_finished |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Tom Forbes):
I had another experiment today. As far as I can see we can pick only one:
1. Support `sendfile` and other efficient means of sending static files
2. Have the response ended signal fire
The WSGI spec [has a section on
this](https://www.python.org/dev/peps/pep-0333/#optional-platform-
specific-file-handling). I'll try and summarize what I have found:
We must give an iterable to `wsgi.file_wrapper`, which can optionally be a
file like object. We currently pass the underlying file-like object given
to the `FileResponse`, which is fine, but when it's `close()` method is
called (or it finishes iterating) then the `FileResponse.close()` is not
called. The `wsgi.file_wrapper` can try and detect if the file is a real
file and if so use more efficient streaming methods.
If we pass the entire `FileResponse` to `wsgi.file_wrapper` then we do not
get fast streaming because the response is not an actual file, but the
`close()` method is called
If we give the underlying user-controlled value the `FileResponse` is
given, we may get streaming but will not get the `FileResponse.close()`
called.
I can see two ways to hack around this:
1. Return a mocked instance that wraps the user-supplied value, with a
`close()` method that calls `FileResponse.close()`. This is tricky because
it *cannot* have attributes or methods like `filenum()` if the
*underlying* value does not, because `hasattr()` will be True and things
will break. The spec gives an example of such a class (grep for `class
FileWrapper:`), but... there are numerous issues with that.
2. Somehow inject our own logic into the values `close()` method and pass
that to `wsgi.wrapper`...
{{{
old_close = value.close
function fake_close(*args, **kwargs):
old_close(*args, **kwargs)
our_response.close() # send signals
value.close = fake_close
}}}
I don't think either is nice.
--
Ticket URL: <https://code.djangoproject.com/ticket/29069#comment:9>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/064.2fea4eb61e5a2101a67c2c559cec6ad6%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.