#30565: Close StreamingHttpResponse content immediately after iterating it
-------------------------------------+-------------------------------------
               Reporter:  Chris      |          Owner:  nobody
  Jerdonek                           |
                   Type:             |         Status:  new
  Uncategorized                      |
              Component:  HTTP       |        Version:  2.2
  handling                           |       Keywords:  HttpResponse,
               Severity:  Normal     |  streaming, StreamingHttpResponse
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 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()
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/30565>
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/052.a44f953a63fb4cb55335b49136603602%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to