Skip to content

Commit ea893bf

Browse files
committed
Add COMPRESS_EVALUATE_CONDITIONAL_REQUEST new behaviour
1 parent 00d2af9 commit ea893bf

File tree

2 files changed

+99
-3
lines changed

2 files changed

+99
-3
lines changed

flask_compress/flask_compress.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ def init_app(self, app):
166166
("COMPRESS_REGISTER", True),
167167
("COMPRESS_STREAMS", True),
168168
("COMPRESS_MUTATE_WEAK_ETAGS", True),
169+
("COMPRESS_EVALUATE_CONDITIONAL_REQUEST", False),
169170
("COMPRESS_ALGORITHM", ["zstd", "br", "gzip", "deflate"]),
170171
]
171172

@@ -236,6 +237,13 @@ def after_request(self, response):
236237
if etag and (not is_weak or app.config["COMPRESS_MUTATE_WEAK_ETAGS"]):
237238
response.set_etag(f"{etag}:{chosen_algorithm}", weak=is_weak)
238239

240+
if (
241+
app.config["COMPRESS_EVALUATE_CONDITIONAL_REQUEST"]
242+
and request.method in ("GET", "HEAD")
243+
and (not response.is_streamed or app.config["COMPRESS_STREAMS"])
244+
):
245+
response.make_conditional(request)
246+
239247
return response
240248

241249
def compressed(self):

tests/test_flask_compress.py

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ def test_mutate_weak_etags(self):
9595
"""Tests COMPRESS_MUTATE_WEAK_ETAGS default value is correctly set."""
9696
self.assertEqual(self.app.config["COMPRESS_MUTATE_WEAK_ETAGS"], True)
9797

98+
def test_evaluate_conditional_request(self):
99+
"""Tests COMPRESS_EVALUATE_CONDITIONAL_REQUEST default value
100+
is correctly set."""
101+
self.assertEqual(
102+
self.app.config["COMPRESS_EVALUATE_CONDITIONAL_REQUEST"], False
103+
)
104+
98105

99106
class InitTests(unittest.TestCase):
100107
def setUp(self):
@@ -589,12 +596,24 @@ def strong():
589596
rv.set_etag("abc123", weak=False)
590597
return rv.make_conditional(request)
591598

599+
@self.app.route("/strong-compress-conditional/")
600+
def strong_compress_conditional():
601+
rv = make_response(render_template("large.html"))
602+
rv.set_etag("abc123", weak=False)
603+
return rv
604+
592605
@self.app.route("/weak/")
593606
def weak():
594607
rv = make_response(render_template("large.html"))
595608
rv.set_etag("abc123", weak=True)
596609
return rv.make_conditional(request)
597610

611+
@self.app.route("/weak-compress-conditional/")
612+
def weak_compress_conditional():
613+
rv = make_response(render_template("large.html"))
614+
rv.set_etag("abc123", weak=True)
615+
return rv
616+
598617
def test_strong_etag_is_mutated_with_suffix_and_remains_strong(self):
599618
client = self.app.test_client()
600619
r = client.get("/strong/", headers=[("Accept-Encoding", "gzip")])
@@ -646,20 +665,89 @@ def test_conditional_get_uses_strong_compressed_representation(self):
646665

647666
r2 = client.get(
648667
"/strong/",
649-
headers=[("Accept-Encoding", "gzip"), ("If-None-Match", r1.headers["ETag"])],
668+
headers=[
669+
("Accept-Encoding", "gzip"),
670+
("If-None-Match", r1.headers["ETag"]),
671+
],
650672
)
651-
# This is the current behavior that breaks strong etags due rewrite
673+
# This is the current behavior that breaks make_conditional
674+
# strong etags due rewrite at after_request
675+
# We would expect a 304 but it does not because of etag mismatch
652676
self.assertEqual(r2.status_code, 200)
653677

654678
def test_conditional_get_uses_weak_compressed_representation(self):
679+
client = self.app.test_client()
680+
r1 = client.get("/weak/", headers=[("Accept-Encoding", "gzip")])
681+
r2 = client.get(
682+
"/weak/",
683+
headers=[
684+
("Accept-Encoding", "gzip"),
685+
("If-None-Match", r1.headers["ETag"]),
686+
],
687+
)
688+
# This is the current behavior that breaks make_conditional
689+
# weak etags due rewrite at after_request
690+
# We would expect a 304 but it does not because of etag mismatch
691+
self.assertEqual(r2.status_code, 200)
692+
693+
def test_conditional_get_uses_strong_compressed_representation_evaluate_conditional(
694+
self,
695+
):
696+
self.app.config["COMPRESS_EVALUATE_CONDITIONAL_REQUEST"] = True
697+
client = self.app.test_client()
698+
r1 = client.get(
699+
"/strong-compress-conditional/", headers=[("Accept-Encoding", "gzip")]
700+
)
701+
etag_header = r1.headers["ETag"]
702+
703+
r2 = client.get(
704+
"/strong-compress-conditional/",
705+
headers=[("Accept-Encoding", "gzip"), ("If-None-Match", etag_header)],
706+
)
707+
# This is the new behaviour we would expect after evaluating
708+
# flask make_conditional at after_request
709+
self.assertEqual(r2.status_code, 304)
710+
self.assertEqual(r2.headers.get("ETag"), etag_header)
711+
self.assertNotIn("Content-Encoding", r2.headers)
712+
self.assertEqual(len(r2.get_data()), 0)
713+
714+
def test_conditional_get_uses_weak_compressed_representation_evaluate_conditional(
715+
self,
716+
):
717+
self.app.config["COMPRESS_EVALUATE_CONDITIONAL_REQUEST"] = True
718+
client = self.app.test_client()
719+
r1 = client.get(
720+
"/weak-compress-conditional/", headers=[("Accept-Encoding", "gzip")]
721+
)
722+
etag_header = r1.headers["ETag"]
723+
724+
r2 = client.get(
725+
"/weak-compress-conditional/",
726+
headers=[("Accept-Encoding", "gzip"), ("If-None-Match", etag_header)],
727+
)
728+
# This is the new behaviour we would expect after evaluating
729+
# flask make_conditional at after_request
730+
self.assertEqual(r2.status_code, 304)
731+
self.assertEqual(r2.headers.get("ETag"), etag_header)
732+
self.assertNotIn("Content-Encoding", r2.headers)
733+
self.assertEqual(len(r2.get_data()), 0)
734+
735+
def test_conditional_get_uses_weak_compressed_representation_no_mutate_etag(self):
655736
self.app.config["COMPRESS_MUTATE_WEAK_ETAGS"] = False
656737
client = self.app.test_client()
657738
r1 = client.get("/weak/", headers=[("Accept-Encoding", "gzip")])
739+
etag_header = r1.headers["ETag"]
740+
658741
r2 = client.get(
659742
"/weak/",
660-
headers=[("Accept-Encoding", "gzip"), ("If-None-Match", r1.headers["ETag"])],
743+
headers=[("Accept-Encoding", "gzip"), ("If-None-Match", etag_header)],
661744
)
745+
# This is the new behaviour we would expect by not mutating
746+
# the weak etags at after_request
662747
self.assertEqual(r2.status_code, 304)
748+
self.assertEqual(r2.headers.get("ETag"), etag_header)
749+
self.assertNotIn("Content-Encoding", r2.headers)
750+
self.assertEqual(len(r2.get_data()), 0)
663751

664752

665753
if __name__ == "__main__":

0 commit comments

Comments
 (0)