Improve gzip decision logic.
Previous called get_data which is dangerous for large but indeterminate response sizes, and the bail chain was more difficult to reason about than a simple should_gzip true/false.
This commit is contained in:
parent
cc2199d59a
commit
9b8159c453
1 changed files with 35 additions and 18 deletions
|
@ -80,29 +80,46 @@ def before_request():
|
||||||
if site.localhost_only and ip != '127.0.0.1':
|
if site.localhost_only and ip != '127.0.0.1':
|
||||||
flask.abort(403)
|
flask.abort(403)
|
||||||
|
|
||||||
gzip_minimum_size = 500
|
gzip_minimum_size = 500 * bytestring.BYTE
|
||||||
gzip_maximum_size = 5 * 2**20
|
gzip_maximum_size = 5 * bytestring.MIBIBYTE
|
||||||
gzip_level = 3
|
gzip_level = 3
|
||||||
|
def should_gzip(response):
|
||||||
|
if response.direct_passthrough:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if response.status_code < 200:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if response.status_code >= 300:
|
||||||
|
return False
|
||||||
|
|
||||||
|
content_length = response.headers.get('Content-Length', None)
|
||||||
|
if content_length is not None and int(content_length) > gzip_maximum_size:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if content_length is not None and int(content_length) < gzip_minimum_size:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if 'Content-Encoding' in response.headers:
|
||||||
|
return False
|
||||||
|
|
||||||
|
accept_encoding = request.headers.get('Accept-Encoding', '')
|
||||||
|
if 'gzip' not in accept_encoding.lower():
|
||||||
|
return False
|
||||||
|
|
||||||
|
content_type = response.headers.get('Content-Type', '')
|
||||||
|
if not (content_type.startswith('application/json') or content_type.startswith('text/')):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
@site.after_request
|
@site.after_request
|
||||||
def after_request(response):
|
def after_request(response):
|
||||||
'''
|
if not should_gzip(response):
|
||||||
Thank you close.io.
|
|
||||||
https://github.com/closeio/Flask-gzip
|
|
||||||
'''
|
|
||||||
accept_encoding = request.headers.get('Accept-Encoding', '')
|
|
||||||
|
|
||||||
bail = False
|
|
||||||
bail = bail or response.status_code < 200
|
|
||||||
bail = bail or response.status_code >= 300
|
|
||||||
bail = bail or response.direct_passthrough
|
|
||||||
bail = bail or int(response.headers.get('Content-Length', 0)) > gzip_maximum_size
|
|
||||||
bail = bail or len(response.get_data()) < gzip_minimum_size
|
|
||||||
bail = bail or 'gzip' not in accept_encoding.lower()
|
|
||||||
bail = bail or 'Content-Encoding' in response.headers
|
|
||||||
|
|
||||||
if bail:
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
gzip_buffer = io.BytesIO()
|
gzip_buffer = io.BytesIO()
|
||||||
gzip_file = gzip.GzipFile(mode='wb', compresslevel=gzip_level, fileobj=gzip_buffer)
|
gzip_file = gzip.GzipFile(mode='wb', compresslevel=gzip_level, fileobj=gzip_buffer)
|
||||||
gzip_file.write(response.get_data())
|
gzip_file.write(response.get_data())
|
||||||
|
|
Loading…
Reference in a new issue