MCPcopy
hub / github.com/urllib3/urllib3 / MultiDecoder

Class MultiDecoder

src/urllib3/response.py:300–353  ·  view source on GitHub ↗

From RFC7231: If one or more encodings have been applied to a representation, the sender that applied the encodings MUST generate a Content-Encoding header field that lists the content codings in the order in which they were applied.

Source from the content-addressed store, hash-verified

298
299
300class MultiDecoder(ContentDecoder):
301 """
302 From RFC7231:
303 If one or more encodings have been applied to a representation, the
304 sender that applied the encodings MUST generate a Content-Encoding
305 header field that lists the content codings in the order in which
306 they were applied.
307 """
308
309 # Maximum allowed number of chained HTTP encodings in the
310 # Content-Encoding header.
311 max_decode_links = 5
312
313 def __init__(self, modes: str) -> None:
314 encodings = [m.strip() for m in modes.split(",")]
315 if len(encodings) > self.max_decode_links:
316 raise DecodeError(
317 "Too many content encodings in the chain: "
318 f"{len(encodings)} > {self.max_decode_links}"
319 )
320 self._decoders = [_get_decoder(e) for e in encodings]
321
322 def flush(self) -> bytes:
323 return self._decoders[0].flush()
324
325 def decompress(self, data: bytes, max_length: int = -1) -> bytes:
326 if max_length <= 0:
327 for d in reversed(self._decoders):
328 data = d.decompress(data)
329 return data
330
331 ret = bytearray()
332 # Every while loop iteration goes through all decoders once.
333 # It exits when enough data is read or no more data can be read.
334 # It is possible that the while loop iteration does not produce
335 # any data because we retrieve up to `max_length` from every
336 # decoder, and the amount of bytes may be insufficient for the
337 # next decoder to produce enough/any output.
338 while True:
339 any_data = False
340 for d in reversed(self._decoders):
341 data = d.decompress(data, max_length=max_length - len(ret))
342 if data:
343 any_data = True
344 # We should not break when no data is returned because
345 # next decoders may produce data even with empty input.
346 ret += data
347 if not any_data or len(ret) >= max_length:
348 return bytes(ret)
349 data = b""
350
351 @property
352 def has_unconsumed_tail(self) -> bool:
353 return any(d.has_unconsumed_tail for d in self._decoders)
354
355
356def _get_decoder(mode: str) -> ContentDecoder:

Callers 1

_get_decoderFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected