colour-science / flask-compress

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

ETag header has to be taken care of #15

Closed aeburriel closed 4 years ago

aeburriel commented 4 years ago

RFC7232 states than ETag header has to be different on varying responses, for instance while compressing (see example 2.3.3). ETag header is used as a uniqueness identifier for resources, very useful for caches.

Some Flask modules make use of this tag, such as flask-rest-api. Presently, flask-compress ignores this tag with is against specification.

My suggestion is to append the compression method to the header, when present, like:

--- flask_compress.py   2020-10-30 18:22:54.993127998 +0100
+++ flask_compress.py   2020-10-30 18:52:50.807618301 +0100
@@ -187,6 +187,8 @@

         response.headers['Content-Encoding'] = chosen_algorithm
         response.headers['Content-Length'] = response.content_length
+        if 'ETag' in response.headers:
+            response.headers['ETag'] = '"%s:%s"' % (response.headers['ETag'][1:-1], chosen_algorithm)

         vary = response.headers.get('Vary')
         if not vary:
alexprengere commented 4 years ago

Thanks for reporting this. I am not too familiar with RFC7232 to I read a bit about it. It looks like ETag headers might be prefixed by W/ for weak validation. In that case I guess your code should be adapted, right? If that is correct, I was thinking:

etag = response.headers.get('ETag')
if etag:
    # "123456789"   => "123456789:gzip"   – A strong ETag validator
    # W/"123456789" => W/"123456789:gzip" – A weak ETag validator
    response.headers['ETag'] = '{0}:{1}"'.format(etag[:-1], chosen_algorithm)
aeburriel commented 4 years ago

My bad, you're absolutely right @alexprengere!