serve static brotli or gzip compressed files as well

This commit is contained in:
codl 2017-08-11 19:44:09 +02:00
parent 10abb9cd2f
commit ed69bdfb12
No known key found for this signature in database
GPG Key ID: 6CD7C8891ED1233A
2 changed files with 30 additions and 7 deletions

View File

@ -1,16 +1,18 @@
import brotli
from flask import request
from brotli import compress
from flask import request, make_response
from functools import wraps
from threading import Thread
from hashlib import sha256
import redis
import os.path
import mimetypes
class BrotliCache(object):
def __init__(self, redis_kwargs={}):
self.redis = redis.StrictRedis(**redis_kwargs)
def compress(self, cache_key, lock_key, body):
encbody = brotli.compress(body)
encbody = compress(body)
self.redis.set(cache_key, encbody, ex=3600)
self.redis.delete(lock_key)
@ -25,13 +27,35 @@ class BrotliCache(object):
encbody = self.redis.get(cache_key)
if encbody:
response.headers.set('content-encoding', 'br')
response.headers.set('vary', 'content-encoding')
response.headers.set('vary', 'accept-encoding')
response.set_data(encbody)
return response
else:
lock_key = 'brotlicache:lock:{}'.format(digest)
if self.redis.set(lock_key, 1, nx=True, ex=60):
if self.redis.set(lock_key, 1, nx=True, ex=10):
t = Thread(target=self.compress, args=(cache_key, lock_key, body))
t.run()
return response
def brotli(app, static = True, dynamic = True):
original_static = app.view_functions['static']
def static_maybe_gzip_brotli(filename=None):
path = os.path.join(app.static_folder, filename)
for encoding, extension in (('br', '.br'), ('gzip', '.gz')):
if encoding not in request.accept_encodings:
continue
encpath = path + extension
if os.path.isfile(encpath):
resp = make_response(original_static(filename=filename + extension))
resp.headers.set('content-encoding', encoding)
resp.headers.set('vary', 'accept-encoding')
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
resp.headers.set('content-type', mimetype)
return resp
return original_static(filename=filename)
if static:
app.view_functions['static'] = static_maybe_gzip_brotli
if dynamic:
cache = BrotliCache()
app.after_request(cache.wrap_response)

View File

@ -36,9 +36,8 @@ def touch_viewer(resp):
db.session.commit()
return resp
brcache = lib.brotli.BrotliCache(app.config.get('REDIS', {}))
app.after_request(brcache.wrap_response)
lib.brotli.brotli(app)
@app.route('/')
def index():