diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2013-10-07 19:52:31 +0200 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2013-10-07 19:52:43 +0200 |
commit | 7e6bd572a64177e1648a52829f077415180daa1f (patch) | |
tree | 0d6309cfec294aea6f3e2ddddea13481f996f5b5 | |
parent | Checksum: reverted b2e7352 due to a case sensitive issue (diff) | |
download | pyload-7e6bd572a64177e1648a52829f077415180daa1f.tar.xz |
gzip compression for api
-rw-r--r-- | pyload/remote/json_converter.py | 11 | ||||
-rw-r--r-- | pyload/web/api_app.py | 32 | ||||
-rw-r--r-- | pyload/web/middlewares.py | 113 | ||||
-rw-r--r-- | pyload/web/utils.py | 10 |
4 files changed, 47 insertions, 119 deletions
diff --git a/pyload/remote/json_converter.py b/pyload/remote/json_converter.py index a7a0645ce..b4e57c4a0 100644 --- a/pyload/remote/json_converter.py +++ b/pyload/remote/json_converter.py @@ -59,6 +59,17 @@ def dumps(*args, **kwargs): return json.dumps(*args, **kwargs) +def dump(*args, **kwargs): + if 'compact' in kwargs and kwargs['compact']: + kwargs['cls'] = BaseEncoderCompact + del kwargs['compact'] + else: + kwargs['cls'] = BaseEncoder + + kwargs['separators'] = separators + return json.dump(*args, **kwargs) + + def loads(*args, **kwargs): kwargs['object_hook'] = convert_obj return json.loads(*args, **kwargs)
\ No newline at end of file diff --git a/pyload/web/api_app.py b/pyload/web/api_app.py index 9370e671f..56e901b06 100644 --- a/pyload/web/api_app.py +++ b/pyload/web/api_app.py @@ -13,6 +13,30 @@ from pyload.Api import ExceptionObject from pyload.remote.json_converter import loads, dumps, BaseEncoder from pyload.utils import remove_chars +# used for gzip compression +try: + import gzip + from cStringIO import StringIO +except ImportError: + gzip = None + StringIO = None + +# gzips response if supported +def json_response(obj): + accept = 'gzip' in request.headers.get('Accept-Encoding', '') + result = dumps(obj) + # don't compress small files + if gzip and accept and len(result) > 500: + response.headers['Vary'] = 'Accept-Encoding' + response.headers['Content-Encoding'] = 'gzip' + zbuf = StringIO() + zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf) + zfile.write(result) + zfile.close() + return zbuf.getvalue() + + return result + # returns http error def error(code, msg): @@ -78,7 +102,7 @@ def call_api(func, args=""): result = getattr(api, func)(*args, **kwargs) # null is invalid json response if result is None: result = True - return dumps(result) + return json_response(result) except ExceptionObject, e: return error(400, e.message) @@ -98,7 +122,7 @@ def login(): user = PYLOAD.checkAuth(username, password, request.environ.get('REMOTE_ADDR', None)) if not user: - return dumps(False) + return json_response(False) s = set_session(request, user) @@ -116,7 +140,7 @@ def login(): if request.params.get('user', None): return dumps(result) - return dumps(sid) + return json_response(sid) @route("/api/logout") @@ -127,4 +151,4 @@ def logout(): s = request.environ.get('beaker.session') s.delete() - return dumps(True) + return json_response(True) diff --git a/pyload/web/middlewares.py b/pyload/web/middlewares.py index 074681b8f..af355bf11 100644 --- a/pyload/web/middlewares.py +++ b/pyload/web/middlewares.py @@ -1,17 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# gzip is optional on some platform -try: - import gzip -except ImportError: - gzip = None - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - class StripPathMiddleware(object): def __init__(self, app): self.app = app @@ -31,105 +20,3 @@ class PrefixMiddleware(object): if path.startswith(self.prefix): e['PATH_INFO'] = path.replace(self.prefix, "", 1) return self.app(e, h) - -# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - -# WSGI middleware -# Gzip-encodes the response. - -# TODO: not in use anymore, because of pre-gzipped resources -class GZipMiddleWare(object): - - def __init__(self, application, compress_level=6): - self.application = application - self.compress_level = int(compress_level) - - def __call__(self, environ, start_response): - if 'gzip' not in environ.get('HTTP_ACCEPT_ENCODING', ''): - # nothing for us to do, so this middleware will - # be a no-op: - return self.application(environ, start_response) - response = GzipResponse(start_response, self.compress_level) - app_iter = self.application(environ, - response.gzip_start_response) - if app_iter is not None: - response.finish_response(app_iter) - - return response.write() - -def header_value(headers, key): - for header, value in headers: - if key.lower() == header.lower(): - return value - -def update_header(headers, key, value): - remove_header(headers, key) - headers.append((key, value)) - -def remove_header(headers, key): - for header, value in headers: - if key.lower() == header.lower(): - headers.remove((header, value)) - break - -class GzipResponse(object): - - def __init__(self, start_response, compress_level): - self.start_response = start_response - self.compress_level = compress_level - self.buffer = StringIO() - self.compressible = False - self.content_length = None - self.headers = () - - def gzip_start_response(self, status, headers, exc_info=None): - self.headers = headers - ct = header_value(headers,'content-type') - ce = header_value(headers,'content-encoding') - cl = header_value(headers, 'content-length') - - # don't compress on unknown size, it may be too huge - cl = int(cl) if cl else 0 - - if ce: - self.compressible = False - elif gzip is not None and ct and (ct.startswith('text/') or ct.startswith('application/')) \ - and 'zip' not in ct and 200 < cl < 1024*1024: - self.compressible = True - headers.append(('content-encoding', 'gzip')) - headers.append(('vary', 'Accept-Encoding')) - - remove_header(headers, 'content-length') - self.headers = headers - self.status = status - return self.buffer.write - - def write(self): - out = self.buffer - out.seek(0) - s = out.getvalue() - out.close() - return [s] - - def finish_response(self, app_iter): - if self.compressible: - output = gzip.GzipFile(mode='wb', compresslevel=self.compress_level, - fileobj=self.buffer) - else: - output = self.buffer - try: - for s in app_iter: - output.write(s) - if self.compressible: - output.close() - finally: - if hasattr(app_iter, 'close'): - try: - app_iter.close() - except : - pass - - content_length = self.buffer.tell() - update_header(self.headers, "Content-Length" , str(content_length)) - self.start_response(self.status, self.headers)
\ No newline at end of file diff --git a/pyload/web/utils.py b/pyload/web/utils.py index e94089185..7e8ee3f13 100644 --- a/pyload/web/utils.py +++ b/pyload/web/utils.py @@ -4,14 +4,21 @@ import re from bottle import request, HTTPError, redirect +try: + import zlib +except ImportError: + zlib = None + from webinterface import PYLOAD, SETUP + def add_json_header(r): r.headers.replace("Content-type", "application/json") r.headers.append("Cache-Control", "no-cache, must-revalidate") r.headers.append("Access-Control-Allow-Origin", request.get_header('Origin', '*')) r.headers.append("Access-Control-Allow-Credentials", "true") + def set_session(request, user): s = request.environ.get('beaker.session') s["uid"] = user.uid @@ -58,15 +65,14 @@ def is_mobile(): return True return False -def select_language(langs): +def select_language(langs): accept = request.headers.get('Accept-Language', '') # TODO return langs[0] - def login_required(perm=None): def _dec(func): def _view(*args, **kwargs): |