0

I have a Flask application for which I have applied successfully caching. However now I need to also send the response in compress mode if and only if the header 'accept-encoding = gzip' is present. Otherwise just sent plain JSON. I am using this example to compress the response. In this case only the JSON is cached. I would like to have both cached. But since Flask-Caching only caches data by using parameters and ignore headers (AFAIK) I am no sure if there is a way to generate two different cache entries using headers also. Each of the two possible Mime type responses (JSON and Zip JSON) should have an entry in the cache. Once is cached the responses to the largest payload (1.41MB) takes 7ms (JSON) and 38ms (JSON-ZIP). So there is a 31 milliseconds to be shaved off if I could cache by header also.

flask== 2.2.2
Flask-Caching==2.0.2
Fabio
  • 555
  • 3
  • 9
  • 24

1 Answers1

0

The only way to get Flask-caching to cache the Gzip response content is by manually calling the set/get methods in the cache. But to do this you need to make sure that all the parameters are given in the URL. So this do not work for POST requests (Although you could customize further). The below code caches the compress content based on the request URL for a GET request. It is only activated on the presence of header 'Content-Encoding'.

@app.after_request
def compress(response):
    accept_encoding = request.headers.get('accept-encoding', '').lower()
    if response.status_code < 200 or response.status_code >= 300 or response.direct_passthrough \
            or 'gzip' not in accept_encoding or 'Content-Encoding' in response.headers:
        return response
    content = cache.get(request.url)
    if not content:
        # 0: no compression, 1: fastest, 9: slowest. Default: 9
        content = gzip.compress(response.get_data(), compresslevel=9)
        if request.method == 'GET':
            # stored compress data only if it is a GET request
            cache.set(request.url, content)
    response.set_data(content)
    response.headers['content-length'] = len(content)
    response.headers['content-encoding'] = 'gzip'
    return response
Fabio
  • 555
  • 3
  • 9
  • 24