Skip to content
This repository was archived by the owner on Oct 30, 2018. It is now read-only.

Commit 34a64a4

Browse files
committed
http.py: use handle_nonhttp_errors() decorator on methods that perform HTTP interaction with Storj Bridge API.
1 parent 46bda59 commit 34a64a4

1 file changed

Lines changed: 55 additions & 8 deletions

File tree

storj/http.py

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,25 @@
2323
# Python 2
2424
JSONDecodeError = ValueError
2525

26-
import model
2726
from api import ecdsa_to_hex
28-
from exception import StorjBridgeApiError
29-
import web_socket
27+
from exception import BridgeError, ClientError
28+
29+
from . import web_socket
30+
from . import model
31+
32+
33+
__logger = logging.getLogger(__name__)
34+
35+
36+
def handle_nonhttp_errors(func):
37+
"""Handle non-HTTP errors."""
38+
def decorator(*args, **kwargs):
39+
try:
40+
return func(*args, **kwargs)
41+
except requests.exceptions.RequestException as e:
42+
__logger.error('Failed to contact the bridge: %s', e)
43+
raise ClientError(message='Failed to contact the bridge')
44+
return decorator
3045

3146

3247
class Client(object):
@@ -139,7 +154,7 @@ def _request(self, **kwargs):
139154
Args:
140155
kwargs (dict): keyword arguments.
141156
Raises:
142-
:py:class:`StorjBridgeApiError`: in case::
157+
:py:class:`BridgeError`: in case::
143158
- internal server error
144159
- error attribute is present in the JSON response
145160
- HTTP response JSON decoding failed
@@ -153,7 +168,7 @@ def _request(self, **kwargs):
153168
except requests.exceptions.RequestException as e:
154169
self.logger.error(e)
155170
self.logger.debug('response.text=%s', response.text)
156-
raise StorjBridgeApiError(response.text)
171+
raise BridgeError(response.text)
157172

158173
# Raise any errors as exceptions
159174
try:
@@ -163,15 +178,16 @@ def _request(self, **kwargs):
163178
return {}
164179

165180
if 'error' in response_json:
166-
raise StorjBridgeApiError(response_json['error'])
181+
raise BridgeError(response_json['error'])
167182

168183
return response_json
169184

170185
except JSONDecodeError as e:
171186
self.logger.error(e)
172187
self.logger.error('_request body %s', response.text)
173-
raise StorjBridgeApiError('Could not decode response.')
188+
raise BridgeError('Could not decode response.')
174189

190+
@handle_nonhttp_errors
175191
def bucket_create(self, name, storage=None, transfer=None):
176192
"""Create storage bucket.
177193
See `API buckets: POST /buckets
@@ -193,6 +209,7 @@ def bucket_create(self, name, storage=None, transfer=None):
193209

194210
return model.Bucket(**self._request(method='POST', path='/buckets', json=data))
195211

212+
@handle_nonhttp_errors
196213
def bucket_delete(self, bucket_id):
197214
"""Destroy a storage bucket.
198215
See `API buckets: DELETE /buckets/{id}
@@ -203,6 +220,7 @@ def bucket_delete(self, bucket_id):
203220
self.logger.info('bucket_delete(%s)', bucket_id)
204221
self._request(method='DELETE', path='/buckets/%s' % bucket_id)
205222

223+
@handle_nonhttp_errors
206224
def bucket_files(self, bucket_id):
207225
"""List all the file metadata stored in the bucket.
208226
See `API buckets: GET /buckets/{id}/files
@@ -218,6 +236,7 @@ def bucket_files(self, bucket_id):
218236
method='GET',
219237
path='/buckets/%s/files/' % (bucket_id), )
220238

239+
@handle_nonhttp_errors
221240
def bucket_get(self, bucket_id):
222241
"""Return the bucket object.
223242
See `API buckets: GET /buckets
@@ -239,8 +258,9 @@ def bucket_get(self, bucket_id):
239258
return None
240259
else:
241260
self.logger.error('bucket_get() error=%s', e)
242-
raise StorjBridgeApiError()
261+
raise BridgeError()
243262

263+
@handle_nonhttp_errors
244264
def bucket_list(self):
245265
"""List all of the buckets belonging to the user.
246266
See `API buckets: GET /buckets
@@ -258,6 +278,7 @@ def bucket_list(self):
258278
else:
259279
raise StopIteration
260280

281+
@handle_nonhttp_errors
261282
def bucket_set_keys(self, bucket_id, bucket_name, keys):
262283
"""Update the bucket with the given public keys.
263284
See `API buckets: PATCH /buckets/{bucket_id}
@@ -278,6 +299,7 @@ def bucket_set_keys(self, bucket_id, bucket_name, keys):
278299
'name': bucket_name,
279300
'pubkeys': keys}))
280301

302+
@handle_nonhttp_errors
281303
def bucket_set_mirrors(self, bucket_id, file_id, redundancy):
282304
"""Establishes a series of mirrors for the given file.
283305
See `API buckets: POST /buckets/{id}/mirrors
@@ -299,6 +321,7 @@ def bucket_set_mirrors(self, bucket_id, file_id, redundancy):
299321
'redundancy': redundancy
300322
}))
301323

324+
@handle_nonhttp_errors
302325
def contact_list(self, page=1, address=None, protocol=None, user_agent=None, connected=None):
303326
"""Lists contacts.
304327
See `API contacts: GET /contacts
@@ -324,6 +347,7 @@ def contact_list(self, page=1, address=None, protocol=None, user_agent=None, con
324347
else:
325348
raise StopIteration
326349

350+
@handle_nonhttp_errors
327351
def contact_lookup(self, node_id):
328352
"""Lookup for contact information of a node.
329353
See `API contacts: GET /contacts/{nodeID}
@@ -339,6 +363,7 @@ def contact_lookup(self, node_id):
339363
method='GET',
340364
path='/contacts/%s' % node_id))
341365

366+
@handle_nonhttp_errors
342367
def file_pointers(self, bucket_id, file_id, skip, limit, exclude=None):
343368
"""Get list of pointers associated with a file.
344369
@@ -373,6 +398,7 @@ def file_pointers(self, bucket_id, file_id, skip, limit, exclude=None):
373398
path='/buckets/%s/files/%s/?skip=%s&limit=%s' % (bucket_id, file_id, skip, limit),
374399
headers={'x-token': pull_token.id})
375400

401+
@handle_nonhttp_errors
376402
def file_download(self, bucket_id, file_id):
377403
self.logger.info('file_pointers(%s, %s)', bucket_id, file_id)
378404

@@ -388,6 +414,7 @@ def file_download(self, bucket_id, file_id):
388414

389415
return file_contents
390416

417+
@handle_nonhttp_errors
391418
def file_metadata(self, bucket_id, file_id):
392419
"""Get file metadata.
393420
See `API buckets: GET /buckets/{id}/files/{file_id}/info
@@ -408,6 +435,7 @@ def file_metadata(self, bucket_id, file_id):
408435
if response is not None:
409436
return model.File(**response)
410437

438+
@handle_nonhttp_errors
411439
def file_upload(self, bucket_id, file, frame):
412440
"""Upload file.
413441
See `API buckets: POST /buckets/{id}/files
@@ -446,6 +474,7 @@ def get_size(file_like_object):
446474
'filename': file.filename,
447475
})
448476

477+
@handle_nonhttp_errors
449478
def file_remove(self, bucket_id, file_id):
450479
"""Delete a file pointer from a specified bucket.
451480
See `API buckets: DELETE /buckets/{id}/files/{file_id}
@@ -460,6 +489,7 @@ def file_remove(self, bucket_id, file_id):
460489
method='DELETE',
461490
path='/buckets/%s/files/%s' % (bucket_id, file_id))
462491

492+
@handle_nonhttp_errors
463493
def frame_add_shard(self, shard, frame_id):
464494
"""Adds a shard item to the staging frame and negotiates a storage contract.
465495
@@ -487,6 +517,7 @@ def frame_add_shard(self, shard, frame_id):
487517

488518
return response
489519

520+
@handle_nonhttp_errors
490521
def file_mirrors(self, bucket_id, file_id):
491522
"""Get list of established and available mirrors associated with a file.
492523
Args:
@@ -511,6 +542,7 @@ def file_mirrors(self, bucket_id, file_id):
511542
else:
512543
raise StopIteration
513544

545+
@handle_nonhttp_errors
514546
def frame_create(self):
515547
"""Creates a file staging frame.
516548
See `API frames: POST /frames
@@ -527,6 +559,7 @@ def frame_create(self):
527559
if response is not None:
528560
return model.Frame(**response)
529561

562+
@handle_nonhttp_errors
530563
def frame_delete(self, frame_id):
531564
"""Destroys the file staging frame by it's unique ID.
532565
See `API frames: DELETE /frames/{frame_id}
@@ -541,6 +574,7 @@ def frame_delete(self, frame_id):
541574
path='/frames/%s' % frame_id,
542575
json={'frame_id': frame_id})
543576

577+
@handle_nonhttp_errors
544578
def frame_get(self, frame_id):
545579
"""Fetches the file staging frame by it's unique ID.
546580
See `API frame: GET /frames/{frame_id}
@@ -560,6 +594,7 @@ def frame_get(self, frame_id):
560594
if response is not None:
561595
return model.Frame(**response)
562596

597+
@handle_nonhttp_errors
563598
def frame_list(self):
564599
"""Returns all open file staging frames.
565600
See `API frame: GET /frames
@@ -579,6 +614,7 @@ def frame_list(self):
579614
else:
580615
raise StopIteration
581616

617+
@handle_nonhttp_errors
582618
def key_delete(self, public_key):
583619
"""Removes a public ECDSA keys.
584620
See `API keys: DELETE /keys/{pubkey}
@@ -649,6 +685,7 @@ def key_import(self, private_keyfile_path, public_keyfile_path):
649685

650686
self.key_register(self.public_key)
651687

688+
@handle_nonhttp_errors
652689
def key_list(self):
653690
"""Lists the public ECDSA keys associated with the user.
654691
See `API keys: GET /keys
@@ -663,6 +700,7 @@ def key_list(self):
663700
path='/keys'
664701
)]
665702

703+
@handle_nonhttp_errors
666704
def key_register(self, public_key):
667705
"""Register an ECDSA public key.
668706
See `API keys: POST /keys
@@ -677,6 +715,7 @@ def key_register(self, public_key):
677715
path='/keys',
678716
json={'key': ecdsa_to_hex(str(public_key))})
679717

718+
@handle_nonhttp_errors
680719
def token_create(self, bucket_id, operation):
681720
"""Creates a token for the specified operation.
682721
See `API buckets: POST /buckets/{id}/tokens
@@ -694,6 +733,7 @@ def token_create(self, bucket_id, operation):
694733
path='/buckets/%s/tokens' % bucket_id,
695734
json={'operation': operation}))
696735

736+
@handle_nonhttp_errors
697737
def send_exchange_report(self, exchange_report_data):
698738
"""Send exchange report to bridge
699739
Args:
@@ -719,6 +759,7 @@ def send_exchange_report(self, exchange_report_data):
719759
path='/reports/exchanges',
720760
json=data))
721761

762+
@handle_nonhttp_errors
722763
def user_activate(self, token):
723764
"""Activate user.
724765
See `API users: GET /activations/{token}
@@ -748,6 +789,7 @@ def check_file_existence_in_bucket(self, bucket_id, filepath, file_id=None):
748789
else:
749790
return False
750791

792+
@handle_nonhttp_errors
751793
def user_activation_email(self, email, token):
752794
"""Send user activation email.
753795
See `API users: POST /activations/{token}
@@ -765,6 +807,7 @@ def user_activation_email(self, email, token):
765807
'email': email,
766808
})
767809

810+
@handle_nonhttp_errors
768811
def user_create(self, email, password):
769812
"""Create a new user with Storj bridge.
770813
See `API users: POST /users
@@ -787,6 +830,7 @@ def user_create(self, email, password):
787830

788831
return response
789832

833+
@handle_nonhttp_errors
790834
def user_deactivate(self, token):
791835
"""Discard activation token.
792836
See `API users: GET /activations/{token}
@@ -800,6 +844,7 @@ def user_deactivate(self, token):
800844
method='DELETE',
801845
path='/activations/%s' % token)
802846

847+
@handle_nonhttp_errors
803848
def user_delete(self, email):
804849
"""Delete user account.
805850
See `API users: DELETE /users/{email}
@@ -813,6 +858,7 @@ def user_delete(self, email):
813858
method='DELETE',
814859
path='/users/%s' % email)
815860

861+
@handle_nonhttp_errors
816862
def user_reset_password(self, email):
817863
"""Request a password reset.
818864
See `API users: PATCH /users/{email}
@@ -826,6 +872,7 @@ def user_reset_password(self, email):
826872
method='PATCH',
827873
path='/users/%s' % email)
828874

875+
@handle_nonhttp_errors
829876
def user_reset_password_confirmation(self, token):
830877
"""Confirm a password reset request.
831878
See `API users: GET /resets/{token}

0 commit comments

Comments
 (0)