77from apify_client ._consts import (
88 API_VERSION ,
99 DEFAULT_API_URL ,
10- DEFAULT_COMPRESSION_ALGORITHM ,
11- DEFAULT_COMPRESSION_QUALITY ,
1210 DEFAULT_MAX_RETRIES ,
1311 DEFAULT_MIN_DELAY_BETWEEN_RETRIES ,
1412 DEFAULT_TIMEOUT_LONG ,
7674from apify_client ._statistics import ClientStatistics
7775from apify_client ._utils import check_custom_headers
7876from apify_client .http_clients import HttpClient , HttpClientAsync , ImpitHttpClient , ImpitHttpClientAsync
77+ from apify_client .http_compressors import GzipHttpCompressor
78+ from apify_client .http_compressors ._base import HttpCompressor
7979
8080if TYPE_CHECKING :
8181 from datetime import timedelta
8282
83- from apify_client .types import CompressionAlgorithm
83+ from apify_client .types import HttpCompressionAlgorithm
84+
85+
86+ def _resolve_compressor (encoding : HttpCompressionAlgorithm | HttpCompressor ) -> HttpCompressor :
87+ """Convert an encoding string or `HttpCompressor` instance into a concrete `HttpCompressor`.
88+
89+ Args:
90+ encoding: Either a string literal (`'gzip'` or `'brotli'`) or an `HttpCompressor` instance.
91+
92+ Returns:
93+ A ready-to-use `HttpCompressor`.
94+
95+ Raises:
96+ ImportError: If `'brotli'` is requested but the `brotli` extra is not installed.
97+ ValueError: If `encoding` is not a recognized compression algorithm.
98+ """
99+ if isinstance (encoding , HttpCompressor ):
100+ return encoding
101+ elif encoding == 'gzip' :
102+ return GzipHttpCompressor ()
103+ elif encoding == 'brotli' :
104+ # The import is here so the ImportError is raised at call time,
105+ # not at module import time, giving users a clear message.
106+ from apify_client .http_compressors import BrotliHttpCompressor # noqa: PLC0415
107+
108+ return BrotliHttpCompressor ()
109+ else :
110+ # The backend supports also `deflate` and `identity` (no compression). One can build
111+ # a custom compressor if needed.
112+ raise ValueError (f'Unsupported compression algorithm: { encoding !r} ' )
84113
85114
86115@docs_group ('Apify API clients' )
@@ -126,8 +155,7 @@ def __init__(
126155 timeout_long : timedelta = DEFAULT_TIMEOUT_LONG ,
127156 timeout_max : timedelta = DEFAULT_TIMEOUT_MAX ,
128157 headers : dict [str , str ] | None = None ,
129- compression_algorithm : CompressionAlgorithm = DEFAULT_COMPRESSION_ALGORITHM ,
130- compression_quality : int = DEFAULT_COMPRESSION_QUALITY ,
158+ encoding : HttpCompressionAlgorithm | HttpCompressor = 'gzip' ,
131159 ) -> None :
132160 """Initialize the Apify API client.
133161
@@ -149,11 +177,9 @@ def __init__(
149177 timeout_long: Default timeout for long-duration API operations (long-polling, streaming, ...).
150178 timeout_max: Maximum timeout cap for exponential timeout growth across retries.
151179 headers: Additional HTTP headers to include in all API requests.
152- compression_algorithm: Algorithm used to compress request bodies. `'brotli'` (default) uses brotli
153- when the `brotli` extra is installed and falls back to gzip when unavailable. `'gzip'` always
154- uses gzip regardless of whether the extra is installed.
155- compression_quality: Compression quality level. Valid range is `1-11` for brotli and `1-9` for gzip.
156- Defaults to `6`.
180+ encoding: Compression algorithm for request bodies. Pass `'gzip'` (default, no extra required) or
181+ `'brotli'` (requires `pip install "apify-client[brotli]"`). For custom quality or full control,
182+ pass an `HttpCompressor` instance directly, e.g. `BrotliHttpCompressor(quality=11)`.
157183 """
158184 # We need to do this because of mocking in tests and default mutable arguments.
159185 api_url = DEFAULT_API_URL if api_url is None else api_url
@@ -216,8 +242,7 @@ def __init__(
216242 self ._timeout_long = timeout_long
217243 self ._timeout_max = timeout_max
218244 self ._headers = headers
219- self ._compression_algorithm = compression_algorithm
220- self ._compression_quality = compression_quality
245+ self ._encoding = encoding
221246
222247 @classmethod
223248 def with_custom_http_client (
@@ -283,8 +308,7 @@ def http_client(self) -> HttpClient:
283308 min_delay_between_retries = self ._min_delay_between_retries ,
284309 statistics = self ._statistics ,
285310 headers = self ._headers ,
286- compression_algorithm = self ._compression_algorithm ,
287- compression_quality = self ._compression_quality ,
311+ compressor = _resolve_compressor (self ._encoding ),
288312 )
289313
290314 return self ._http_client
@@ -491,8 +515,7 @@ def __init__(
491515 timeout_long : timedelta = DEFAULT_TIMEOUT_LONG ,
492516 timeout_max : timedelta = DEFAULT_TIMEOUT_MAX ,
493517 headers : dict [str , str ] | None = None ,
494- compression_algorithm : CompressionAlgorithm = DEFAULT_COMPRESSION_ALGORITHM ,
495- compression_quality : int = DEFAULT_COMPRESSION_QUALITY ,
518+ encoding : HttpCompressionAlgorithm | HttpCompressor = 'gzip' ,
496519 ) -> None :
497520 """Initialize the Apify API client.
498521
@@ -514,11 +537,9 @@ def __init__(
514537 timeout_long: Default timeout for long-duration API operations (long-polling, streaming, ...).
515538 timeout_max: Maximum timeout cap for exponential timeout growth across retries.
516539 headers: Additional HTTP headers to include in all API requests.
517- compression_algorithm: Algorithm used to compress request bodies. `'brotli'` (default) uses brotli
518- when the `brotli` extra is installed and falls back to gzip when unavailable. `'gzip'` always
519- uses gzip regardless of whether the extra is installed.
520- compression_quality: Compression quality level. Valid range is `1-11` for brotli and `1-9` for gzip.
521- Defaults to `6`.
540+ encoding: Compression algorithm for request bodies. Pass `'gzip'` (default, no extra required) or
541+ `'brotli'` (requires `pip install "apify-client[brotli]"`). For custom quality or full control,
542+ pass an `HttpCompressor` instance directly, e.g. `BrotliHttpCompressor(quality=11)`.
522543 """
523544 # We need to do this because of mocking in tests and default mutable arguments.
524545 api_url = DEFAULT_API_URL if api_url is None else api_url
@@ -581,8 +602,7 @@ def __init__(
581602 self ._timeout_long = timeout_long
582603 self ._timeout_max = timeout_max
583604 self ._headers = headers
584- self ._compression_algorithm = compression_algorithm
585- self ._compression_quality = compression_quality
605+ self ._encoding = encoding
586606
587607 @classmethod
588608 def with_custom_http_client (
@@ -648,8 +668,7 @@ def http_client(self) -> HttpClientAsync:
648668 min_delay_between_retries = self ._min_delay_between_retries ,
649669 statistics = self ._statistics ,
650670 headers = self ._headers ,
651- compression_algorithm = self ._compression_algorithm ,
652- compression_quality = self ._compression_quality ,
671+ compressor = _resolve_compressor (self ._encoding ),
653672 )
654673 return self ._http_client
655674
0 commit comments