summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-10-07 19:52:31 +0200
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-10-07 19:52:43 +0200
commit7e6bd572a64177e1648a52829f077415180daa1f (patch)
tree0d6309cfec294aea6f3e2ddddea13481f996f5b5
parentChecksum: reverted b2e7352 due to a case sensitive issue (diff)
downloadpyload-7e6bd572a64177e1648a52829f077415180daa1f.tar.xz
gzip compression for api
-rw-r--r--pyload/remote/json_converter.py11
-rw-r--r--pyload/web/api_app.py32
-rw-r--r--pyload/web/middlewares.py113
-rw-r--r--pyload/web/utils.py10
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):