Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support brotli compression of HTTP responses #2945

Closed
wants to merge 3 commits into from

Conversation

roganov
Copy link
Contributor

@roganov roganov commented Apr 18, 2018

What do these changes do?

This PR adds support for br (brotli) content-type compression.

I have also refactored compressors and decompressors to a separate module (aiohttp.compression) because there are some differences between zlib's and brotli's intefraces.

Related tests have also been refactored a bit, now pytest's parametrization is used more aggressively.

For now brotli compression of websocket responses is not supported,

Are there changes in behavior for the user?

aiohttp now can compress responses using brotli compression algorithm if brotlipy is installed.

Related issue number

Closes #2518

@asvetlov
Copy link
Member

Thanks for PR.
I have some notes, will make a detailed review in the evening.

@codecov-io
Copy link

codecov-io commented Apr 18, 2018

Codecov Report

Merging #2945 into master will decrease coverage by 0.17%.
The diff coverage is 89.58%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2945      +/-   ##
==========================================
- Coverage   97.99%   97.81%   -0.18%     
==========================================
  Files          40       41       +1     
  Lines        7520     7613      +93     
  Branches     1318     1333      +15     
==========================================
+ Hits         7369     7447      +78     
- Misses         48       56       +8     
- Partials      103      110       +7
Impacted Files Coverage Δ
aiohttp/http_writer.py 100% <100%> (ø) ⬆️
aiohttp/client_reqrep.py 97.27% <100%> (ø) ⬆️
aiohttp/multipart.py 95.41% <100%> (-0.06%) ⬇️
aiohttp/http_parser.py 97.98% <100%> (-0.07%) ⬇️
aiohttp/web_response.py 98.14% <100%> (-0.04%) ⬇️
aiohttp/compression.py 87.8% <87.8%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 26802e0...91e5dc3. Read the comment docs.

Copy link
Member

@asvetlov asvetlov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work.
I have some notes about implementation but very like the overall design.

Switching to ContentCoding usage instead of strings in both client and server API would be nice (but we should keep supporting strings during deprecation period)


@classmethod
def get_from_accept_encoding(cls, accept_encoding):
accept_encoding = accept_encoding.lower()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to parse AcceptEncoding header properly and respect weights instead of selecting the first supported compression based on server preference order.
Multiple Accept-Encoding headers are allowed by HTTP spec also.
We can either accept a list of headers (req.headers.getall('Accept-Encoding')) or headers param itself.

return coding

@classmethod
def values(cls):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the usage of the method?
Could we utilize Enum.__members__ or another existing Enum API?

return _values


def get_compressor(encoding):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we switch here to ContentCoding enum? Maybe make it a ContentCoding member function?

The same for decompressor.

self._finished = False

@classmethod
def gzip(cls):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer making GZipCompressor class derived from ZlibCompressor over class methods for gzip and deflate compressors building.

return self._compress.finish()


def decompress(encoding, data):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I see the function is used only once in multipart module.
Maybe direct usage of decompressor classes there is enough?

@roganov
Copy link
Contributor Author

roganov commented Apr 25, 2018

Just a status update: have been busy lately, but planning to finish by the end of the week.

@asvetlov
Copy link
Member

asvetlov commented Apr 25, 2018 via email

@asvetlov
Copy link
Member

Is there a progress on it?

@roganov
Copy link
Contributor Author

roganov commented Jun 21, 2018

HI
I'm very sorry it's taking me so long. I plan to finish next week.

@asvetlov
Copy link
Member

No problem

@asvetlov
Copy link
Member

There are many conflicts now.
I suspect after applying black the difference will grow.
@roganov do you want to make it done?
Otherwise I'll close the PR

@roganov
Copy link
Contributor Author

roganov commented Dec 3, 2018

I'll close this one and reopen when I'm ready. Really sorry, don't have enough free time currently.

@roganov roganov closed this Dec 3, 2018
@lock
Copy link

lock bot commented Dec 3, 2019

This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.

If you feel like there's important points made in this discussion,
please include those exceprts into that new issue.

@lock lock bot added the outdated label Dec 3, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Dec 3, 2019
@psf-chronographer psf-chronographer bot added the bot:chronographer:provided There is a change note present in this PR label Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bot:chronographer:provided There is a change note present in this PR outdated
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement brotli everywhere
3 participants