diff options
| author | 2013-10-07 19:52:31 +0200 | |
|---|---|---|
| committer | 2013-10-07 19:52:43 +0200 | |
| commit | 7e6bd572a64177e1648a52829f077415180daa1f (patch) | |
| tree | 0d6309cfec294aea6f3e2ddddea13481f996f5b5 /pyload/web | |
| parent | Checksum: reverted b2e7352 due to a case sensitive issue (diff) | |
| download | pyload-7e6bd572a64177e1648a52829f077415180daa1f.tar.xz | |
gzip compression for api
Diffstat (limited to 'pyload/web')
| -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 | 
3 files changed, 36 insertions, 119 deletions
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):  | 
