#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 django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. 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.