#30565: HttpResponseBase.close not called when using FileResponse / WSGI "file
wrapper" object
-------------------------------------+-------------------------------------
Reporter: Chris Jerdonek | Owner: nobody
Type: Uncategorized | Status: new
Component: HTTP handling | Version: master
Severity: Normal | Resolution:
Keywords: HttpResponse, | Triage Stage:
streaming, StreamingHttpResponse | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Chris Jerdonek):
> You implemented some kind of custom FileResponse and for some reason the
file object you pass as the streaming_content argument is not being
closed. Is this correct so far?
No, that was in my original post before I had developed a correct
understanding of the issue. After diagnosing the issue, I updated the
ticket's title with the new understanding ("HttpResponseBase.close not
called when using FileResponse / WSGI "file wrapper" object") and changed
the first sentence of my original post to read, "See comment #6 further
down for the correct, updated description for this ticket."
What I think should be addressed is that either the code comment above
`HttpResponseBase.close()` should be clarified to say that it's not called
if "file_wrapper" is used, or else `FileResponse._set_streaming_content()`
should wrap the file-like object's `close()` method so that when the WSGI
server calls `close()` on the file-like object, it also calls `close()` on
the corresponding `HttpResponseBase` object. (I provided a proof-of-
concept for how that can be done in
[https://code.djangoproject.com/timeline?from=2019-06-15T03%3A11%3A43-05%3A00&precision=second
last comment above].)
Here are a few reasons I think the latter should be done. First,
`HttpResponseBase.close()` raises the `request_finished` signal, which
Django's documentation
[https://docs.djangoproject.com/en/2.2/ref/signals/#django.core.signals.request_finished
says] is "sent when Django finishes delivering an HTTP response to the
client." There are a number of valid reasons someone might want to act on
the end of the request. Currently, people won't be getting that signal
simply because "file_wrapper" happens to be used, and they might not know
they aren't. "file_wrapper" is just an optimization, so it doesn't seem
like it should be affecting Django's behavior otherwise.
The second reason is that it's not obvious for the developer to know in
advance if "file_wrapper" will be used because a number of conditions need
to met and those conditions even depend on the deployment setting (e.g.
whether the environment contains `wsgi.file_wrapper`). So it's hard for
the developer to know whether they can rely on the `request_finished`
signal for a given request.
Third, Django's code even seems to expect that `HttpResponseBase.close()`
will be called in the "file_wrapper" case because in its "file_wrapper"
code path `FileResponse._set_streaming_content()` adds the file-like
object to `self._closable_objects`, which is only used / needed in the
`HttpResponseBase.close()` case.
An alternative idea for a code change would be not to wrap the file-like
object's `close()` so that it calls `HttpResponseBase.close()`, but
instead to (1) update the code comment to clarify that it's not called
when "file_wrapper" is used, and (2) wrap the file-like object's `close()`
so that it sends the `request_finished` signal. That way developers will
be able to rely upload the `request_finished` signal in both situations.
--
Ticket URL: <https://code.djangoproject.com/ticket/30565#comment:10>
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/067.a0683bc33a33b170c9c0774a2b66afd7%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.