decoder.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. # -*- coding: utf-8 -*-
  2. """
  3. hyper/common/decoder
  4. ~~~~~~~~~~~~~~~~~~~~
  5. Contains hyper's code for handling compressed bodies.
  6. """
  7. import zlib
  8. class DeflateDecoder(object):
  9. """
  10. This is a decoding object that wraps ``zlib`` and is used for decoding
  11. deflated content.
  12. This rationale for the existence of this object is pretty unpleasant.
  13. The HTTP RFC specifies that 'deflate' is a valid content encoding. However,
  14. the spec _meant_ the zlib encoding form. Unfortunately, people who didn't
  15. read the RFC very carefully actually implemented a different form of
  16. 'deflate'. Insanely, ``zlib`` handles them using two wbits values. This is
  17. such a mess it's hard to adequately articulate.
  18. This class was lovingly borrowed from the excellent urllib3 library under
  19. license: see NOTICES. If you ever see @shazow, you should probably buy him
  20. a drink or something.
  21. """
  22. def __init__(self):
  23. self._first_try = True
  24. self._data = b''
  25. self._obj = zlib.decompressobj(zlib.MAX_WBITS)
  26. def __getattr__(self, name):
  27. return getattr(self._obj, name)
  28. def decompress(self, data):
  29. if not self._first_try:
  30. return self._obj.decompress(data)
  31. self._data += data
  32. try:
  33. return self._obj.decompress(data)
  34. except zlib.error:
  35. self._first_try = False
  36. self._obj = zlib.decompressobj(-zlib.MAX_WBITS)
  37. try:
  38. return self.decompress(self._data)
  39. finally:
  40. self._data = None