Skip to content

Commit

Permalink
Add strategy argument to StreamResponse.enable_compression() meth…
Browse files Browse the repository at this point in the history
…od (#6257)
  • Loading branch information
shootkin authored Sep 10, 2024
1 parent 94685fb commit b8eca27
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGES/6257.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Added ``strategy`` parameter to :meth:`aiohttp.web.StreamResponse.enable_compression`
The value of this parameter is passed to the :func:`zlib.compressobj` function, allowing people
to use a more sufficient compression algorithm for their data served by :mod:`aiohttp.web`
-- by :user:`shootkin`
1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ Kevin Samuel
Kimmo Parviainen-Jalanko
Kirill Klenov
Kirill Malovitsa
Konstantin Shutkin
Konstantin Valetov
Krzysztof Blazewicz
Kyrylo Perevozchikov
Expand Down
5 changes: 4 additions & 1 deletion aiohttp/abc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import socket
import zlib
from abc import ABC, abstractmethod
from collections.abc import Sized
from http.cookies import BaseCookie, Morsel
Expand Down Expand Up @@ -204,7 +205,9 @@ async def drain(self) -> None:
"""Flush the write buffer."""

@abstractmethod
def enable_compression(self, encoding: str = "deflate") -> None:
def enable_compression(
self, encoding: str = "deflate", strategy: int = zlib.Z_DEFAULT_STRATEGY
) -> None:
"""Enable HTTP body compression"""

@abstractmethod
Expand Down
14 changes: 12 additions & 2 deletions aiohttp/web_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import math
import time
import warnings
import zlib
from concurrent.futures import Executor
from http import HTTPStatus
from typing import (
Expand Down Expand Up @@ -77,6 +78,7 @@ class StreamResponse(BaseClass, HeadersMixin, CookieMixin):
"_chunked",
"_compression",
"_compression_force",
"_compression_strategy",
"_req",
"_payload_writer",
"_eof_sent",
Expand Down Expand Up @@ -105,6 +107,7 @@ def __init__(
self._keep_alive: Optional[bool] = None
self._chunked = False
self._compression = False
self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY
self._compression_force: Optional[ContentCoding] = None

self._req: Optional[BaseRequest] = None
Expand Down Expand Up @@ -184,10 +187,15 @@ def enable_chunked_encoding(self) -> None:
"You can't enable chunked encoding when a content length is set"
)

def enable_compression(self, force: Optional[ContentCoding] = None) -> None:
def enable_compression(
self,
force: Optional[ContentCoding] = None,
strategy: int = zlib.Z_DEFAULT_STRATEGY,
) -> None:
"""Enables response compression encoding."""
self._compression = True
self._compression_force = force
self._compression_strategy = strategy

@property
def headers(self) -> "CIMultiDict[str]":
Expand Down Expand Up @@ -319,7 +327,9 @@ async def _do_start_compression(self, coding: ContentCoding) -> None:
if coding != ContentCoding.identity:
assert self._payload_writer is not None
self._headers[hdrs.CONTENT_ENCODING] = coding.value
self._payload_writer.enable_compression(coding.value)
self._payload_writer.enable_compression(
coding.value, self._compression_strategy
)
# Compressed payload may have different content length,
# remove the header
self._headers.popall(hdrs.CONTENT_LENGTH, None)
Expand Down
5 changes: 4 additions & 1 deletion docs/web_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ and :ref:`aiohttp-web-signals` handlers::

.. seealso:: :meth:`enable_compression`

.. method:: enable_compression(force=None)
.. method:: enable_compression(force=None, strategy=zlib.Z_DEFAULT_STRATEGY)

Enable compression.

Expand All @@ -659,6 +659,9 @@ and :ref:`aiohttp-web-signals` handlers::
*Accept-Encoding* is not checked if *force* is set to a
:class:`ContentCoding`.

*strategy* accepts a :mod:`zlib` compression strategy.
See :func:`zlib.compressobj` for possible values.

.. seealso:: :attr:`compression`

.. attribute:: chunked
Expand Down
11 changes: 6 additions & 5 deletions tests/test_web_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import json
import re
import weakref
import zlib
from concurrent.futures import ThreadPoolExecutor
from typing import Any, AsyncIterator, Optional
from unittest import mock
Expand Down Expand Up @@ -421,7 +422,7 @@ async def test_compression_default_coding() -> None:

msg = await resp.prepare(req)

msg.enable_compression.assert_called_with("deflate")
msg.enable_compression.assert_called_with("deflate", zlib.Z_DEFAULT_STRATEGY)
assert "deflate" == resp.headers.get(hdrs.CONTENT_ENCODING)
assert msg.filter is not None

Expand All @@ -436,7 +437,7 @@ async def test_force_compression_deflate() -> None:
assert resp.compression

msg = await resp.prepare(req)
msg.enable_compression.assert_called_with("deflate")
msg.enable_compression.assert_called_with("deflate", zlib.Z_DEFAULT_STRATEGY)
assert "deflate" == resp.headers.get(hdrs.CONTENT_ENCODING)


Expand All @@ -448,7 +449,7 @@ async def test_force_compression_no_accept_deflate() -> None:
assert resp.compression

msg = await resp.prepare(req)
msg.enable_compression.assert_called_with("deflate")
msg.enable_compression.assert_called_with("deflate", zlib.Z_DEFAULT_STRATEGY)
assert "deflate" == resp.headers.get(hdrs.CONTENT_ENCODING)


Expand All @@ -462,7 +463,7 @@ async def test_force_compression_gzip() -> None:
assert resp.compression

msg = await resp.prepare(req)
msg.enable_compression.assert_called_with("gzip")
msg.enable_compression.assert_called_with("gzip", zlib.Z_DEFAULT_STRATEGY)
assert "gzip" == resp.headers.get(hdrs.CONTENT_ENCODING)


Expand All @@ -474,7 +475,7 @@ async def test_force_compression_no_accept_gzip() -> None:
assert resp.compression

msg = await resp.prepare(req)
msg.enable_compression.assert_called_with("gzip")
msg.enable_compression.assert_called_with("gzip", zlib.Z_DEFAULT_STRATEGY)
assert "gzip" == resp.headers.get(hdrs.CONTENT_ENCODING)


Expand Down

0 comments on commit b8eca27

Please sign in to comment.