colour-science / flask-compress

Compress responses of your Flask application.
MIT License
117 stars 27 forks source link

Using Flash-caching results in caching of non-compressed files #44

Open Kacper-Lisikiewicz-THG opened 1 year ago

Kacper-Lisikiewicz-THG commented 1 year ago

When using the flask-caching===2.0.2 library together with flask-compress==1.14.0 I run into an issue where the caching doesn't work properly. I tested three scenarios:

1. using just the @cache.cached(timeout=600, query_string=True) decorator: as expected the cached response is not compressed but the one served to the webpage is compressed

2. using the @cache.cached(timeout=600, query_string=True) decorator and

    compress.cache = cache
    compress.cache_key = get_cache_key

    # Define a function to return cache key for incoming requests
def get_cache_key(request):
    return request.url

Taking the get_cache_key function from documentation results in caching both the non-compressed response and the compressed response.

3.

def get_cache_key(request):
    args_as_sorted_tuple = tuple(
        sorted(pair for pair in request.args.items(multi=True))
    )
    # ... now hash the sorted (key, value) tuple so it can be
    # used as a key for cache. Turn them into bytes so that the
    # hash function will accept them
    args_as_bytes = str(args_as_sorted_tuple).encode()
    cache_hash = hashlib.md5(args_as_bytes)

    cache_hash = str(cache_hash.hexdigest())

    cache_key = request.path + cache_hash

    return cache_key

unifying the get_cache_key functions so that they return the same cache key results in an error

eds-eds-1 | Traceback (most recent call last): eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/gunicorn/workers/gthread.py", line 271, in handle eds-eds-1 | keepalive = self.handle_request(req, conn) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/gunicorn/workers/gthread.py", line 323, in handle_request eds-eds-1 | respiter = self.wsgi(environ, resp.start_response) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2213, in call eds-eds-1 | return self.wsgi_app(environ, start_response) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2193, in wsgi_app eds-eds-1 | response = self.handle_exception(e) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/flask_cors/extension.py", line 165, in wrapped_function eds-eds-1 | return cors_after_request(app.make_response(f(*args, **kwargs))) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2190, in wsgi_app eds-eds-1 | response = self.full_dispatch_request() eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1487, in full_dispatch_request eds-eds-1 | return self.finalize_request(rv) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1508, in finalize_request eds-eds-1 | response = self.process_response(response) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2002, in process_response eds-eds-1 | response = self.ensure_sync(func)(response) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/flask_compress/flask_compress.py", line 208, in after_request eds-eds-1 | response.set_data(compressed_content) eds-eds-1 | File "/usr/local/lib/python3.9/site-packages/werkzeug/wrappers/response.py", line 302, in set_data eds-eds-1 | self.headers["Content-Length"] = str(len(value)) eds-eds-1 | TypeError: object of type 'Response' has no len()

I want to cache only the compressed response to save resources, am I doing something wrong, or is that a bug in either of the packages?