Skip to content
This repository has been archived by the owner on Mar 29, 2022. It is now read-only.

Commit

Permalink
Support brotli compressed payloads (Content-Encoding: br)
Browse files Browse the repository at this point in the history
  • Loading branch information
vfaronov committed Sep 4, 2016
1 parent c28ef01 commit 2192655
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 13 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ This project adheres to `Semantic Versioning <http://semver.org/>`_
Unreleased
~~~~~~~~~~

Added
-----
- Decompression of `brotli`_ compressed payloads (``Content-Encoding: br``).

.. _brotli: https://tools.ietf.org/html/rfc7932

Removed
-------
- The deprecated constants
``httpolice.ERROR``, ``httpolice.COMMENT``, ``httpolice.DEBUG``
have been removed. Use ``httpolice.Severity`` instead.
Expand Down
10 changes: 6 additions & 4 deletions doc/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ __ https://pypi.python.org/pypi/HTTPolice

If you’re not familiar with pip,
you may need to install it `manually`__ or `from your OS distribution`__.
You may also need development files and tools for `lxml`__ dependencies.
You may also need development files and tools to compile dependencies.

__ https://pip.pypa.io/en/stable/installing/
__ https://packaging.python.org/en/latest/install_requirements_linux/
__ http://lxml.de/installation.html

`PyPy`__ (the 2.7 variant) is also supported,
but you may experience problems with older PyPy versions (5.3.1 should be OK).
Expand All @@ -29,8 +28,7 @@ On Debian/Ubuntu

::

$ sudo apt-get install python-dev libxml2-dev libxslt1-dev zlib1g-dev
$ sudo apt-get install python-pip
$ sudo apt-get install python-pip python-dev libxml2-dev libxslt1-dev zlib1g-dev libffi-dev

Then, to install the HTTPolice command-line tool into ``~/.local/bin``::

Expand Down Expand Up @@ -62,6 +60,10 @@ __ https://pypi.python.org/pypi/lxml/3.6.0
__ https://pypi.python.org/pypi/lxml/3.6.1
__ https://www.python.org/downloads/windows/

The same applies to `brotlipy`__.

__ https://pypi.python.org/pypi/brotlipy

Then you can install HTTPolice itself::

C:\>Python27\Scripts\pip install HTTPolice
Expand Down
6 changes: 6 additions & 0 deletions httpolice/codings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@
import io
import zlib

import brotli


def decode_gzip(data):
return gzip.GzipFile(fileobj=io.BytesIO(data)).read()


def decode_deflate(data):
return zlib.decompress(data)


def decode_brotli(data):
return brotli.decompress(data)
16 changes: 7 additions & 9 deletions httpolice/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import six

from httpolice.blackboard import Blackboard, derived_property
from httpolice.codings import decode_deflate, decode_gzip
from httpolice.codings import decode_brotli, decode_deflate, decode_gzip
from httpolice.header import HeadersView
from httpolice.known import cc, h, header, media, media_type, tc, upgrade, warn
from httpolice.structure import (FieldName, HeaderEntry, HTTPVersion,
Expand Down Expand Up @@ -73,15 +73,13 @@ def decoded_body(self):
codings = self.headers.content_encoding.value[:]
while codings and okay(r) and r:
coding = codings.pop()
if coding in [cc.gzip, cc.x_gzip]:
decoder = {cc.gzip: decode_gzip,
cc.x_gzip: decode_gzip,
cc.deflate: decode_deflate,
cc.br: decode_brotli}.get(coding)
if decoder is not None:
try:
r = decode_gzip(r)
except Exception as e:
self.complain(1037, coding=coding, error=e)
r = Unavailable
elif coding == cc.deflate:
try:
r = decode_deflate(r)
r = decoder(r)
except Exception as e:
self.complain(1037, coding=coding, error=e)
r = Unavailable
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
'bitstring >= 3.1.4',
'dominate >= 2.2.0',
'defusedxml >= 0.4.1',
'brotlipy >= 0.5.1',
],
extras_require={
':python_version == "2.7"': [
Expand Down
15 changes: 15 additions & 0 deletions test/combined_data/1037_3
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
1037

======== BEGIN INBOUND STREAM ========
GET / HTTP/1.1
Host: example.com
User-Agent: demo

======== BEGIN OUTBOUND STREAM ========
HTTP/1.1 200 OK
Date: Thu, 31 Dec 2015 18:26:56 GMT
Content-Type: text/plain
Content-Length: 14
Content-Encoding: br

Hello world!
Binary file added test/combined_data/content_encoding_br
Binary file not shown.
5 changes: 5 additions & 0 deletions test/test_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,8 @@ def test_alt_svc():
MultiDict([(u'foo', u'bar')])
),
]


def test_decode_brotli():
[exch1] = load_from_file('content_encoding_br')
assert exch1.responses[0].decoded_body.startswith(b'Lorem ipsum dolor')

0 comments on commit 2192655

Please sign in to comment.