Skip to content

Commit f5462ca

Browse files
committed
Fix gzip content encoding quality negotiation
Honor q=0 when clients explicitly reject gzip encoding. Add WSGI regression cases for gzip quality parameters. Signed-off-by: Metin Hatipogullari <metin.hatipogullari@gmail.com>
1 parent 9cd073c commit f5462ca

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

‎prometheus_client/exposition.py‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,18 @@ def _get_escaping(accept_header: List[str]) -> str:
429429
def gzip_accepted(accept_encoding_header: str) -> bool:
430430
accept_encoding_header = accept_encoding_header or ''
431431
for accepted in accept_encoding_header.split(','):
432-
if accepted.split(';')[0].strip().lower() == 'gzip':
433-
return True
432+
encoding, *params = accepted.split(';')
433+
if encoding.strip().lower() != 'gzip':
434+
continue
435+
for param in params:
436+
key, sep, value = param.strip().partition('=')
437+
if sep and key.strip().lower() == 'q':
438+
try:
439+
quality = float(value.strip())
440+
except ValueError:
441+
return False
442+
return 0 < quality <= 1
443+
return True
434444
return False
435445

436446

‎tests/test_wsgi.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,19 @@ def test_gzip_disabled(self):
112112
outputs = app(gzip_environ, self.capture)
113113
# Assert outputs are not compressed.
114114
self.assert_outputs(outputs, metric_name, help_text, increments, compressed=False)
115+
116+
def test_gzip_quality(self):
117+
self.increment_metrics("counter", "A counter", 2)
118+
app = make_wsgi_app(self.registry)
119+
for encoding, compressed in [
120+
("gzip;q=0", False),
121+
("gzip;q=0.0", False),
122+
("br, GZip; Q=0", False),
123+
("gzip;q=0.5", True),
124+
("gzip;q=bogus", False),
125+
]:
126+
with self.subTest(encoding=encoding):
127+
environ = dict(self.environ)
128+
environ['HTTP_ACCEPT_ENCODING'] = encoding
129+
outputs = app(environ, self.capture)
130+
self.assert_outputs(outputs, "counter", "A counter", 2, compressed)

0 commit comments

Comments
 (0)