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

Implement per-view compression as discussed in #12 #14

Merged
merged 1 commit into from
Nov 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Implement per-view compression as discussed in #12
  • Loading branch information
alexprengere committed Oct 19, 2020
commit 405eec755f28020a326d4714132b11f32b5c7c87
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ $ easy_install flask-compress

## Using Flask-Compress

### Globally

Flask-Compress is incredibly simple to use. In order to start compressing your Flask application's assets, the first thing to do is let Flask-Compress know about your [`flask.Flask`](http://flask.pocoo.org/docs/latest/api/#flask.Flask) application object.

```python
Expand All @@ -75,6 +77,25 @@ def start_app():

In terms of automatically compressing your assets, passing your [`flask.Flask`](http://flask.pocoo.org/docs/latest/api/#flask.Flask) object to the `flask_compress.Compress` object is all that needs to be done.

### Per-view compression

Compression is possible per view using the `@compress.compressed()` decorator. Make sure to disable global compression first.

```python
from flask import Flask
from flask_compress import Compress

app = Flask(__name__)
app.config["COMPRESS_REGISTER"] = False # disable default compression of all eligible requests
compress = Compress()
compress.init_app(app)

# Compress this view specifically
@app.route("/test")
@compress.compressed()
def view():
pass
```

## Options

Expand Down
14 changes: 13 additions & 1 deletion flask_compress.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
# License: The MIT License (MIT)

import sys
import functools
from gzip import GzipFile
import zlib
from io import BytesIO

from collections import defaultdict

import brotli
from flask import request, current_app
from flask import request, after_this_request, current_app


if sys.version_info[:2] == (2, 6):
Expand Down Expand Up @@ -196,6 +197,17 @@ def after_request(self, response):

return response

def compressed(self):
def decorator(f):
@functools.wraps(f)
def decorated_function(*args, **kwargs):
@after_this_request
def compressor(response):
return self.after_request(response)
return f(*args, **kwargs)
return decorated_function
return decorator

def compress(self, app, response, algorithm):
if algorithm == 'gzip':
gzip_buffer = BytesIO()
Expand Down
31 changes: 31 additions & 0 deletions tests/test_flask_compress.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,5 +297,36 @@ def test_content_encoding_is_correct(self):
self.assertEqual(response_deflate.headers.get('Content-Encoding'), 'deflate')


class CompressionPerViewTests(unittest.TestCase):
def setUp(self):
self.app = Flask(__name__)
self.app.testing = True
self.app.config["COMPRESS_REGISTER"] = False
compress = Compress()
compress.init_app(self.app)

@self.app.route('/route1/')
def view_1():
return render_template('large.html')

@self.app.route('/route2/')
@compress.compressed()
def view_2():
return render_template('large.html')

def test_compression(self):
client = self.app.test_client()
headers = [('Accept-Encoding', 'deflate')]

response = client.get('/route1/', headers=headers)
self.assertEqual(response.status_code, 200)
self.assertNotIn('Content-Encoding', response.headers)

response = client.get('/route2/', headers=headers)
self.assertEqual(response.status_code, 200)
self.assertIn('Content-Encoding', response.headers)
self.assertEqual(response.headers.get('Content-Encoding'), 'deflate')


if __name__ == '__main__':
unittest.main()