From 7555e20158df4fa4a724be26eeb5d68ed2ef4508 Mon Sep 17 00:00:00 2001 From: drebs Date: Fri, 29 Sep 2017 18:38:48 -0300 Subject: [bug] check all http response status codes --- src/leap/soledad/client/_db/blobs.py | 55 ++++++++++++++++++------------------ src/leap/soledad/server/_blobs.py | 18 ++++++++++-- 2 files changed, 42 insertions(+), 31 deletions(-) (limited to 'src/leap') diff --git a/src/leap/soledad/client/_db/blobs.py b/src/leap/soledad/client/_db/blobs.py index 6d47999a..e997c6ff 100644 --- a/src/leap/soledad/client/_db/blobs.py +++ b/src/leap/soledad/client/_db/blobs.py @@ -132,11 +132,13 @@ class ConnectionPool(adbapi.ConnectionPool): return handle -def check_http_status(code): +def check_http_status(code, blob_id=None, flags=None): + if code == 404: + raise BlobNotFoundError(blob_id) if code == 409: - raise BlobAlreadyExistsError() + raise BlobAlreadyExistsError(blob_id) elif code == 406: - raise InvalidFlagsError() + raise InvalidFlagsError((blob_id, flags)) elif code != 200: raise SoledadError("Server Error: %s" % code) @@ -253,8 +255,9 @@ class BlobManager(object): :rtype: twisted.internet.defer.Deferred """ uri = urljoin(self.remote, self.user + '/') - data = yield self._client.get(uri, params=params) - defer.returnValue((yield data.json())) + response = yield self._client.get(uri, params=params) + check_http_status(response.code) + defer.returnValue((yield response.json())) def local_list(self, namespace='', sync_status=None): return self.local.list(namespace, sync_status) @@ -350,15 +353,10 @@ class BlobManager(object): :return: A deferred that fires when the operation finishes. :rtype: twisted.internet.defer.Deferred """ - flags = BytesIO(json.dumps(flags)) + flagsfd = BytesIO(json.dumps(flags)) uri = urljoin(self.remote, self.user + "/" + blob_id) - response = yield self._client.post(uri, data=flags, params=params) - if response.code == 404: - logger.error("Blob not found during set_flags: %s" % blob_id) - msg = "No blob found on server while trying to set flags: %s" - raise SoledadError(msg % (blob_id)) - - check_http_status(response.code) + response = yield self._client.post(uri, data=flagsfd, params=params) + check_http_status(response.code, blob_id=blob_id, flags=flags) @defer.inlineCallbacks def get_flags(self, blob_id, **params): @@ -378,9 +376,7 @@ class BlobManager(object): uri = urljoin(self.remote, self.user + "/" + blob_id) params.update({'only_flags': True}) response = yield self._client.get(uri, params=params) - if response.code == 404: - logger.error("Blob not found in server: %r" % blob_id) - raise BlobNotFoundError(blob_id) + check_http_status(response.code, blob_id=blob_id) defer.returnValue((yield response.json())) @defer.inlineCallbacks @@ -435,7 +431,7 @@ class BlobManager(object): armor=False) fd = yield crypter.encrypt() response = yield self._client.put(uri, data=fd, params=params) - check_http_status(response.code) + check_http_status(response.code, blob_id) logger.info("Finished upload: %s" % (blob_id,)) @defer.inlineCallbacks @@ -444,20 +440,20 @@ class BlobManager(object): # TODO this needs to be connected in a tube uri = urljoin(self.remote, self.user + '/' + blob_id) params = {'namespace': namespace} if namespace else None - data = yield self._client.get(uri, params=params, namespace=namespace) - - if data.code == 404: - logger.warn("Blob not found in server: %s" % blob_id) - defer.returnValue(None) - elif not data.headers.hasHeader('Tag'): - logger.error("Server didn't send a tag header for: %s" % blob_id) - defer.returnValue(None) - tag = data.headers.getRawHeaders('Tag')[0] + response = yield self._client.get(uri, params=params, + namespace=namespace) + check_http_status(response.code, blob_id=blob_id) + + if not response.headers.hasHeader('Tag'): + msg = "Server didn't send a tag header for: %s" % blob_id + logger.error(msg) + raise SoledadError(msg) + tag = response.headers.getRawHeaders('Tag')[0] tag = base64.urlsafe_b64decode(tag) buf = DecrypterBuffer(blob_id, self.secret, tag) # incrementally collect the body of the response - yield treq.collect(data, buf.write) + yield treq.collect(response, buf.write) fd, size = buf.close() logger.info("Finished download: (%s, %d)" % (blob_id, size)) defer.returnValue((fd, size)) @@ -482,10 +478,13 @@ class BlobManager(object): if (yield self.local.exists(blob_id, namespace)): yield self.local.delete(blob_id, namespace) + @defer.inlineCallbacks def _delete_from_remote(self, blob_id, **params): # TODO this needs to be connected in a tube uri = urljoin(self.remote, self.user + '/' + blob_id) - return self._client.delete(uri, params=params) + response = yield self._client.delete(uri, params=params) + check_http_status(response.code, blob_id=blob_id) + defer.returnValue(response) class SQLiteBlobBackend(object): diff --git a/src/leap/soledad/server/_blobs.py b/src/leap/soledad/server/_blobs.py index 790a9b51..cacfe38d 100644 --- a/src/leap/soledad/server/_blobs.py +++ b/src/leap/soledad/server/_blobs.py @@ -124,8 +124,11 @@ class FilesystemBlobsBackend(object): with open(path, 'wb') as blobfile: yield fbp.startProducing(blobfile) - def delete_blob(self, user, blob_id, namespace=''): + def delete_blob(self, user, blob_id, request, namespace=''): blob_path = self._get_path(user, blob_id, namespace) + if not os.path.isfile(blob_path): + request.setResponseCode(404) + return "Blob doesn't exists: %s" % blob_id os.unlink(blob_path) try: os.unlink(blob_path + '.flags') @@ -175,7 +178,12 @@ class FilesystemBlobsBackend(object): return self._get_disk_usage(self._get_path(user)) def add_tag_header(self, user, blob_id, request, namespace=''): - with open(self._get_path(user, blob_id, namespace)) as doc_file: + blob_path = self._get_path(user, blob_id, namespace) + if not os.path.isfile(blob_path): + # 404 - Not Found + request.setResponseCode(404) + return "Blob doesn't exists: %s" % blob_id + with open(blob_path) as doc_file: doc_file.seek(-16, 2) tag = base64.urlsafe_b64encode(doc_file.read()) request.responseHeaders.setRawHeaders('Tag', [tag]) @@ -202,6 +210,10 @@ class FilesystemBlobsBackend(object): raise Exception(err) return desired_path + def exists(self, user, blob_id, namespace): + return os.path.isfile( + self._get_path(user, blob_id=blob_id, namespace=namespace)) + def _get_path(self, user, blob_id='', namespace=''): parts = [user] if blob_id: @@ -262,7 +274,7 @@ class BlobsResource(resource.Resource): def render_DELETE(self, request): logger.info("http put: %s" % request.path) user, blob_id, namespace = self._validate(request) - self._handler.delete_blob(user, blob_id, namespace) + self._handler.delete_blob(user, blob_id, request, namespace=namespace) return '' def render_PUT(self, request): -- cgit v1.2.3