diff options
author | Lars Wirzenius <liw@liw.fi> | 2017-10-06 19:26:31 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2017-10-09 21:01:58 +0300 |
commit | 2e101cf1813806b5315947ef13c1d77507a65813 (patch) | |
tree | 5641669725729a62e1c7e14078ade4f0c07e834f | |
parent | b4baa19b7d0668475ecd0c9e02be794322ab7f5f (diff) | |
download | qvisqve-2e101cf1813806b5315947ef13c1d77507a65813.tar.gz |
Add: GET/PUT for blobs
-rw-r--r-- | qvarn/api.py | 75 |
1 files changed, 71 insertions, 4 deletions
diff --git a/qvarn/api.py b/qvarn/api.py index 33ba867..b7b8cc7 100644 --- a/qvarn/api.py +++ b/qvarn/api.py @@ -226,7 +226,7 @@ class QvarnAPI: } return ok_response(version) - def resource_routes(self, path, rt): + def resource_routes(self, path, rt): # pragma: no cover coll = qvarn.CollectionAPI() coll.set_object_store(self._store) coll.set_resource_type(rt) @@ -268,12 +268,15 @@ class QvarnAPI: files = rt.get_files() for subpath in rt.get_subpaths(): if subpath not in files: - routes.extend( - self.get_subresource_routes(id_path, coll, subpath)) + more = self.get_subresource_routes(id_path, coll, subpath) + else: + more = self.get_file_routes(id_path, coll, subpath) + routes.extend(more) return routes + self._get_notification_routes(coll, path, id_path) - def get_subresource_routes(self, id_path, coll, subpath): + def get_subresource_routes( + self, id_path, coll, subpath): # pragma: no cover return [ { 'method': 'GET', @@ -287,6 +290,20 @@ 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() @@ -629,6 +646,40 @@ class QvarnAPI: return 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 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 no_such_resource_response(str(e)) + + headers = { + 'Revision': new_sub['revision'], + } + return ok_response('', headers) + return wrapper + def get_resource_callback(self, coll): # pragma: no cover def wrapper(content_type, body, **kwargs): try: @@ -647,6 +698,22 @@ class QvarnAPI: return 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 no_such_resource_response(str(e)) + headers = { + 'Content-Type': sub_obj['content_type'], + 'Revision': obj['revision'], + } + return 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() |