﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
30565	"HttpResponseBase.close not called when using FileResponse / WSGI ""file wrapper"" object"	Chris Jerdonek	Chris Jerdonek	"See [https://code.djangoproject.com/timeline?from=2019-06-15T02%3A26%3A50-05%3A00&precision=second comment #6] further down for the correct, updated description for this ticket.

This ticket is to suggest doing for `StreamingHttpResponse` what #25725 did for `HttpReponse`, namely to close the underlying content iterator after it has been iterated over.

Currently, if creating a `StreamingHttpResponse` from a file-like object, it doesn't seem like there's an obvious way to close the underlying file after the file has been streamed. And as [https://code.djangoproject.com/ticket/25725#comment:1 one of the comments] in #25725 pointed out, trying to do this in `StreamingHttpResponse.close()` isn't a good solution because WSGI servers can't be relied upon to call `close()`.

I believe an alternative, more reliable solution may be to call `close()` immediately after the iterator has been exhausted (if `hasattr(value, 'close')` is true, as #25725 does). This is essentially what #25725 did for non-streaming `HttpResponse` objects. Here is that code:

{{{
#!python
def content(self, value):
    # Consume iterators upon assignment to allow repeated iteration.
    if hasattr(value, '__iter__') and not isinstance(value, (bytes, str)):
        content = b''.join(self.make_bytes(chunk) for chunk in value)
        if hasattr(value, 'close'):
            try:
                value.close()
            except Exception:
                pass
    else:
        content = self.make_bytes(value)
}}}


(from 
https://github.com/django/django/blob/1564e42ad397021093585147875a21dae1a3b3fc/django/http/response.py#L310-L319 )

In the streaming case, the content `value` argument could be wrapped something like so (inside `StreamingHttpResponse._set_streaming_content(value)`):

{{{
#!python
def iter_content():
    yield from value
    if hasattr(value, 'close'):
        try:
            value.close()
        except Exception:
            pass

new_value = iter_content()
}}}

Here is the current code for `StreamingHttpResponse._set_streaming_content()`: 

{{{
#!python
def _set_streaming_content(self, value):
    # Ensure we can never iterate on ""value"" more than once.
    self._iterator = iter(value)
    if hasattr(value, 'close'):
        self._closable_objects.append(value)
}}}

(from: https://github.com/django/django/blob/1564e42ad397021093585147875a21dae1a3b3fc/django/http/response.py#L376-L380)

"	Bug	closed	HTTP handling	dev	Normal	fixed	HttpResponse, streaming, StreamingHttpResponse	Johannes Maron	Ready for checkin	1	0	0	0	0	0
