diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2018-08-14 19:25:05 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-14 19:25:05 -0400 |
commit | 157a4e409551f4008e15e38fd3991aadcd8abbcd (patch) | |
tree | b4d9ebde516261b4aa6453678c781bfe1c65a92c | |
parent | 8090b79ea406d9d5f909432267f81ce90542c2dd (diff) | |
parent | 94c31e8c1d8851584210afbc2b6e1d4882c48c87 (diff) | |
download | cherrypy-git-17.2.0.tar.gz |
Merge pull request #1692 from SURFscz/masterv17.2.0
Fix static file cached 304 response
-rw-r--r-- | CHANGES.rst | 6 | ||||
-rw-r--r-- | cherrypy/_cprequest.py | 12 | ||||
-rw-r--r-- | cherrypy/lib/caching.py | 15 | ||||
-rwxr-xr-x | setup.py | 1 |
4 files changed, 31 insertions, 3 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 6618df7e..44f377fc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,9 @@ +v17.2.0 +------- + +* :issue:`1690`: Prevent orphaned Event object in cached + 304 response. + v17.1.0 ------- diff --git a/cherrypy/_cprequest.py b/cherrypy/_cprequest.py index f9943ff7..bde09891 100644 --- a/cherrypy/_cprequest.py +++ b/cherrypy/_cprequest.py @@ -2,9 +2,12 @@ import sys import time import uuid + import six from six.moves.http_cookies import SimpleCookie, CookieError +from more_itertools.recipes import consume + import cherrypy from cherrypy._cpcompat import text_or_bytes, ntob from cherrypy import _cpreqbody @@ -879,6 +882,14 @@ class Response(object): self.body = newbody return newbody + def _flush_body(self): + """ + Discard self.body but consume any generator such that + any finalization can occur, such as is required by + caching.tee_output(). + """ + consume(iter(self.body)) + def finalize(self): """Transform headers (and cookies) into self.header_list. (Core)""" try: @@ -903,6 +914,7 @@ class Response(object): # and 304 (not modified) responses MUST NOT # include a message-body." dict.pop(headers, 'Content-Length', None) + self._flush_body() self.body = b'' else: # Responses which are not streamed should have a Content-Length, diff --git a/cherrypy/lib/caching.py b/cherrypy/lib/caching.py index aa265164..fed325a6 100644 --- a/cherrypy/lib/caching.py +++ b/cherrypy/lib/caching.py @@ -405,10 +405,19 @@ def tee_output(): output.append(chunk) yield chunk - # save the cache data + # Save the cache data, but only if the body isn't empty. + # e.g. a 304 Not Modified on a static file response will + # have an empty body. + # If the body is empty, delete the cache because it + # contains a stale Threading._Event object that will + # stall all consecutive requests until the _Event times + # out body = b''.join(output) - cherrypy._cache.put((response.status, response.headers or {}, - body, response.time), len(body)) + if not body: + cherrypy._cache.delete() + else: + cherrypy._cache.put((response.status, response.headers or {}, + body, response.time), len(body)) response = cherrypy.serving.response response.body = tee(response.body) @@ -63,6 +63,7 @@ params = dict( 'six>=1.11.0', 'cheroot>=6.2.4', 'portend>=2.1.1', + 'more_itertools', ], extras_require={ 'docs': [ |