diff --git a/swh/objstorage/api/client.py b/swh/objstorage/api/client.py index 437e4a5..b359931 100644 --- a/swh/objstorage/api/client.py +++ b/swh/objstorage/api/client.py @@ -1,72 +1,48 @@ -# Copyright (C) 2015-2016 The Software Heritage developers +# Copyright (C) 2015-2017 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information -import pickle -import requests +from swh.core.api import SWHRemoteAPI -from requests.exceptions import ConnectionError from ..objstorage import ObjStorage from ..exc import ObjStorageAPIError -from .common import (decode_response, - encode_data_client as encode_data) -class RemoteObjStorage(ObjStorage): - """ Proxy to a remote object storage. +class RemoteObjStorage(ObjStorage, SWHRemoteAPI): + """Proxy to a remote object storage. This class allows to connect to an object storage server via http protocol. Attributes: url (string): The url of the server to connect. Must end with a '/' session: The session to send requests. + """ def __init__(self, url): - self.url = url - self.session = requests.Session() - - def _url(self, endpoint): - return '%s%s' % (self.url, endpoint) - - def post(self, endpoint, data): - try: - response = self.session.post( - self._url(endpoint), - data=encode_data(data), - headers={'content-type': 'application/x-msgpack'}, - ) - except ConnectionError as e: - raise ObjStorageAPIError(e) - - # XXX: this breaks language-independence and should be - # replaced by proper unserialization - if response.status_code == 400: - raise pickle.loads(decode_response(response)) - - return decode_response(response) + super().__init__(api_exception=ObjStorageAPIError, url=url) def check_config(self, *, check_write): return self.post('check_config', {'check_write': check_write}) def __contains__(self, obj_id): return self.post('content/contains', {'obj_id': obj_id}) def add(self, content, obj_id=None, check_presence=True): return self.post('content/add', {'content': content, 'obj_id': obj_id, 'check_presence': check_presence}) def get(self, obj_id): return self.post('content/get', {'obj_id': obj_id}) def get_batch(self, obj_ids): return self.post('content/get/batch', {'obj_ids': obj_ids}) def check(self, obj_id): self.post('content/check', {'obj_id': obj_id}) def get_random(self, batch_size): return self.post('content/get/random', {'batch_size': batch_size}) diff --git a/swh/objstorage/api/common.py b/swh/objstorage/api/common.py index 328d826..8b883f2 100644 --- a/swh/objstorage/api/common.py +++ b/swh/objstorage/api/common.py @@ -1,69 +1,47 @@ # Copyright (C) 2015 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information import json import pickle from flask import Request, Response from swh.core.serializers import msgpack_dumps, msgpack_loads, SWHJSONDecoder class BytesRequest(Request): """Request with proper escaping of arbitrary byte sequences.""" encoding = 'utf-8' encoding_errors = 'surrogateescape' def encode_data_server(data): return Response( msgpack_dumps(data), mimetype='application/x-msgpack', ) -def encode_data_client(data): - try: - return msgpack_dumps(data) - except OverflowError as e: - raise ValueError('Limits were reached. Please, check your input.\n' + - str(e)) - - def decode_request(request): content_type = request.mimetype data = request.get_data() if content_type == 'application/x-msgpack': r = msgpack_loads(data) elif content_type == 'application/json': r = json.loads(data, cls=SWHJSONDecoder) else: raise ValueError('Wrong content type `%s` for API request' % content_type) return r -def decode_response(response): - content_type = response.headers['content-type'] - - if content_type.startswith('application/x-msgpack'): - r = msgpack_loads(response.content) - elif content_type.startswith('application/json'): - r = response.json(cls=SWHJSONDecoder) - else: - raise ValueError('Wrong content type `%s` for API response' - % content_type) - - return r - - def error_handler(exception, encoder): # XXX: this breaks language-independence and should be # replaced by proper serialization of errors response = encoder(pickle.dumps(exception)) response.status_code = 400 return response