summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2017-10-12 12:09:53 +0300
committerLars Wirzenius <liw@liw.fi>2017-10-12 12:09:53 +0300
commitc7bb0a2055edc6dcfcc6f1eb4ffa819955979960 (patch)
treeaa5449685a93947e5029f06a8af81b081d53fe3d
parent3bd8b255e7336fdadfd53ea94f59f10c7d621456 (diff)
downloadqvisqve-c7bb0a2055edc6dcfcc6f1eb4ffa819955979960.tar.gz
Refactor: move file serving to its own module
-rw-r--r--qvarn/__init__.py1
-rw-r--r--qvarn/api.py71
-rw-r--r--qvarn/file_router.py98
3 files changed, 104 insertions, 66 deletions
diff --git a/qvarn/__init__.py b/qvarn/__init__.py
index 7e3d221..6321b69 100644
--- a/qvarn/__init__.py
+++ b/qvarn/__init__.py
@@ -96,6 +96,7 @@ from .responses import (
)
from .router import Router
+from .file_router import FileRouter
from .version_router import VersionRouter
from .timestamp import get_current_timestamp
diff --git a/qvarn/api.py b/qvarn/api.py
index 9719a56..639a554 100644
--- a/qvarn/api.py
+++ b/qvarn/api.py
@@ -247,7 +247,11 @@ class QvarnAPI:
if subpath not in files:
more = self.get_subresource_routes(id_path, coll, subpath)
else:
- more = self.get_file_routes(id_path, coll, subpath)
+ file_router = qvarn.FileRouter()
+ file_router.set_subpath(subpath)
+ file_router.set_object_store(self._store)
+ file_router.set_parent_collection(coll)
+ more = file_router.get_routes()
routes.extend(more)
return routes + self._get_notification_routes(coll, path, id_path)
@@ -267,20 +271,6 @@ class QvarnAPI:
},
]
- def get_file_routes(self, id_path, objcoll, subpath): # pragma: no cover
- return [
- {
- 'method': 'GET',
- 'path': '{}/{}'.format(id_path, subpath),
- 'callback': self.get_file_callback(objcoll, subpath),
- },
- {
- 'method': 'PUT',
- 'path': '{}/{}'.format(id_path, subpath),
- 'callback': self.put_file_callback(objcoll, subpath),
- },
- ]
-
def _get_notification_routes(self, coll, path, id_path):
rt = self.get_listener_resource_type()
listeners = qvarn.CollectionAPI()
@@ -616,41 +606,6 @@ class QvarnAPI:
return qvarn.ok_response(result_body)
return wrapper
- def put_file_callback(self, objcoll, subpath): # pragma: no cover
- def wrapper(content_type, body, **kwargs):
- obj_id = kwargs['id']
-
- # FIXME: add header getting to apifw
- import bottle
- revision = bottle.request.get_header('Revision')
-
- obj = objcoll.get(obj_id)
- if obj['revision'] != revision:
- qvarn.log.log(
- 'error',
- msg_text='Client gave wrong revision',
- revision_from_client=revision,
- current_revision=obj['revision'])
- return qvarn.conflict_response(
- 'Bad revision {}'.format(revision))
-
- sub_obj = objcoll.get_subresource(obj_id, subpath)
- sub_obj['content_type'] = content_type
- new_sub = objcoll.put_subresource(
- sub_obj, subpath=subpath, obj_id=obj_id, revision=revision)
-
- try:
- self._store.remove_blob(subpath=subpath, obj_id=obj_id)
- self._store.create_blob(body, subpath=subpath, obj_id=obj_id)
- except qvarn.NoSuchObject as e:
- return qvarn.no_such_resource_response(str(e))
-
- headers = {
- 'Revision': new_sub['revision'],
- }
- return qvarn.ok_response('', headers)
- return wrapper
-
def get_resource_callback(self, coll): # pragma: no cover
def wrapper(content_type, body, **kwargs):
try:
@@ -669,22 +624,6 @@ class QvarnAPI:
return qvarn.ok_response(obj)
return wrapper
- def get_file_callback(self, coll, subpath): # pragma: no cover
- def wrapper(content_type, body, **kwargs):
- obj_id = kwargs['id']
- try:
- obj = coll.get(obj_id)
- sub_obj = coll.get_subresource(obj_id, subpath)
- blob = self._store.get_blob(obj_id=obj_id, subpath=subpath)
- except (qvarn.NoSuchResource, qvarn.NoSuchObject) as e:
- return qvarn.no_such_resource_response(str(e))
- headers = {
- 'Content-Type': sub_obj['content_type'],
- 'Revision': obj['revision'],
- }
- return qvarn.ok_response(blob, headers)
- return wrapper
-
def get_resource_list_callback(self, coll): # pragma: no cover
def wrapper(content_type, body, **kwargs):
body = coll.list()
diff --git a/qvarn/file_router.py b/qvarn/file_router.py
new file mode 100644
index 0000000..b7e4507
--- /dev/null
+++ b/qvarn/file_router.py
@@ -0,0 +1,98 @@
+# Copyright (C) 2017 Lars Wirzenius
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+import qvarn
+
+
+class FileRouter(qvarn.Router):
+
+ def __init__(self):
+ super().__init__()
+ self._store = None
+ self._parent_coll = None
+ self._subpath = None
+
+ def set_subpath(self, subpath):
+ self._subpath = subpath
+
+ def set_parent_collection(self, parent_coll):
+ self._parent_coll = parent_coll
+
+ def set_object_store(self, store):
+ self._store = store
+
+ def get_routes(self):
+ rt = self._parent_coll.get_type()
+ file_path = '{}/<id>/{}'.format(rt.get_path(), self._subpath)
+ return [
+ {
+ 'method': 'GET',
+ 'path': file_path,
+ 'callback': self._get_file,
+ },
+ {
+ 'method': 'PUT',
+ 'path': file_path,
+ 'callback': self._put_file,
+ },
+ ]
+
+ def _get_file(self, *args, **kwargs):
+ obj_id = kwargs['id']
+ try:
+ obj = self._parent_coll.get(obj_id)
+ sub_obj = self._parent_coll.get_subresource(obj_id, self._subpath)
+ blob = self._store.get_blob(obj_id=obj_id, subpath=self._subpath)
+ except (qvarn.NoSuchResource, qvarn.NoSuchObject) as e:
+ return qvarn.no_such_resource_response(str(e))
+ headers = {
+ 'Content-Type': sub_obj['content_type'],
+ 'Revision': obj['revision'],
+ }
+ return qvarn.ok_response(blob, headers)
+
+ def _put_file(self, content_type, body, *args, **kwargs):
+ obj_id = kwargs['id']
+
+ # FIXME: add header getting to apifw
+ import bottle
+ revision = bottle.request.get_header('Revision')
+
+ obj = self._parent_coll.get(obj_id)
+ if obj['revision'] != revision:
+ qvarn.log.log(
+ 'error',
+ msg_text='Client gave wrong revision',
+ revision_from_client=revision,
+ current_revision=obj['revision'])
+ return qvarn.conflict_response(
+ 'Bad revision {}'.format(revision))
+
+ sub_obj = self._parent_coll.get_subresource(obj_id, self._subpath)
+ sub_obj['content_type'] = content_type
+ new_sub = self._parent_coll.put_subresource(
+ sub_obj, subpath=self._subpath, obj_id=obj_id, revision=revision)
+
+ try:
+ self._store.remove_blob(obj_id=obj_id, subpath=self._subpath)
+ self._store.create_blob(body, obj_id=obj_id, subpath=self._subpath)
+ except qvarn.NoSuchObject as e:
+ return qvarn.no_such_resource_response(str(e))
+
+ headers = {
+ 'Revision': new_sub['revision'],
+ }
+ return qvarn.ok_response('', headers)