|
42 | 42 | from .typedefs import JSONEncoder, LooseHeaders
|
43 | 43 |
|
44 | 44 | REASON_PHRASES = {http_status.value: http_status.phrase for http_status in HTTPStatus}
|
| 45 | +LARGE_BODY_SIZE = 1024**2 |
45 | 46 |
|
46 | 47 | __all__ = ("ContentCoding", "StreamResponse", "Response", "json_response")
|
47 | 48 |
|
@@ -397,25 +398,26 @@ def _generate_content_type_header(
|
397 | 398 | self._headers[CONTENT_TYPE] = ctype
|
398 | 399 |
|
399 | 400 | async def _do_start_compression(self, coding: ContentCoding) -> None:
|
400 |
| - if coding != ContentCoding.identity: |
401 |
| - assert self._payload_writer is not None |
402 |
| - self._headers[hdrs.CONTENT_ENCODING] = coding.value |
403 |
| - self._payload_writer.enable_compression(coding.value) |
404 |
| - # Compressed payload may have different content length, |
405 |
| - # remove the header |
406 |
| - self._headers.popall(hdrs.CONTENT_LENGTH, None) |
| 401 | + if coding is ContentCoding.identity: |
| 402 | + return |
| 403 | + assert self._payload_writer is not None |
| 404 | + self._headers[hdrs.CONTENT_ENCODING] = coding.value |
| 405 | + self._payload_writer.enable_compression(coding.value) |
| 406 | + # Compressed payload may have different content length, |
| 407 | + # remove the header |
| 408 | + self._headers.popall(hdrs.CONTENT_LENGTH, None) |
407 | 409 |
|
408 | 410 | async def _start_compression(self, request: "BaseRequest") -> None:
|
409 | 411 | if self._compression_force:
|
410 | 412 | await self._do_start_compression(self._compression_force)
|
411 |
| - else: |
412 |
| - # Encoding comparisons should be case-insensitive |
413 |
| - # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1 |
414 |
| - accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, "").lower() |
415 |
| - for value, coding in CONTENT_CODINGS.items(): |
416 |
| - if value in accept_encoding: |
417 |
| - await self._do_start_compression(coding) |
418 |
| - return |
| 413 | + return |
| 414 | + # Encoding comparisons should be case-insensitive |
| 415 | + # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1 |
| 416 | + accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, "").lower() |
| 417 | + for value, coding in CONTENT_CODINGS.items(): |
| 418 | + if value in accept_encoding: |
| 419 | + await self._do_start_compression(coding) |
| 420 | + return |
419 | 421 |
|
420 | 422 | async def prepare(self, request: "BaseRequest") -> Optional[AbstractStreamWriter]:
|
421 | 423 | if self._eof_sent:
|
@@ -765,30 +767,28 @@ async def _start(self, request: "BaseRequest") -> AbstractStreamWriter:
|
765 | 767 | async def _do_start_compression(self, coding: ContentCoding) -> None:
|
766 | 768 | if self._chunked or isinstance(self._body, Payload):
|
767 | 769 | return await super()._do_start_compression(coding)
|
768 |
| - |
769 |
| - if coding != ContentCoding.identity: |
770 |
| - # Instead of using _payload_writer.enable_compression, |
771 |
| - # compress the whole body |
772 |
| - compressor = ZLibCompressor( |
773 |
| - encoding=str(coding.value), |
774 |
| - max_sync_chunk_size=self._zlib_executor_size, |
775 |
| - executor=self._zlib_executor, |
776 |
| - ) |
777 |
| - assert self._body is not None |
778 |
| - if self._zlib_executor_size is None and len(self._body) > 1024 * 1024: |
779 |
| - warnings.warn( |
780 |
| - "Synchronous compression of large response bodies " |
781 |
| - f"({len(self._body)} bytes) might block the async event loop. " |
782 |
| - "Consider providing a custom value to zlib_executor_size/" |
783 |
| - "zlib_executor response properties or disabling compression on it." |
784 |
| - ) |
785 |
| - self._compressed_body = ( |
786 |
| - await compressor.compress(self._body) + compressor.flush() |
| 770 | + if coding is ContentCoding.identity: |
| 771 | + return |
| 772 | + # Instead of using _payload_writer.enable_compression, |
| 773 | + # compress the whole body |
| 774 | + compressor = ZLibCompressor( |
| 775 | + encoding=coding.value, |
| 776 | + max_sync_chunk_size=self._zlib_executor_size, |
| 777 | + executor=self._zlib_executor, |
| 778 | + ) |
| 779 | + assert self._body is not None |
| 780 | + if self._zlib_executor_size is None and len(self._body) > LARGE_BODY_SIZE: |
| 781 | + warnings.warn( |
| 782 | + "Synchronous compression of large response bodies " |
| 783 | + f"({len(self._body)} bytes) might block the async event loop. " |
| 784 | + "Consider providing a custom value to zlib_executor_size/" |
| 785 | + "zlib_executor response properties or disabling compression on it." |
787 | 786 | )
|
788 |
| - assert self._compressed_body is not None |
789 |
| - |
790 |
| - self._headers[hdrs.CONTENT_ENCODING] = coding.value |
791 |
| - self._headers[hdrs.CONTENT_LENGTH] = str(len(self._compressed_body)) |
| 787 | + self._compressed_body = ( |
| 788 | + await compressor.compress(self._body) + compressor.flush() |
| 789 | + ) |
| 790 | + self._headers[hdrs.CONTENT_ENCODING] = coding.value |
| 791 | + self._headers[hdrs.CONTENT_LENGTH] = str(len(self._compressed_body)) |
792 | 792 |
|
793 | 793 |
|
794 | 794 | def json_response(
|
|
0 commit comments