Skip to content

Commit

Permalink
Implement per-view compression as discussed in #12 (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexprengere authored Nov 2, 2020
1 parent 262c401 commit 8cb22c4
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
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()

0 comments on commit 8cb22c4

Please sign in to comment.