okina: refine errors handling (#31557)

This commit is contained in:
Thomas NOËL 2019-03-19 16:34:24 +01:00 committed by Frédéric Péters
parent c2bf9eb3b0
commit 1d798fb874
2 changed files with 43 additions and 32 deletions

View File

@ -36,24 +36,41 @@ class Okina(BaseResource):
class Meta:
verbose_name = _('Okina')
def request(self, endpoint, payload=None, result_is_json=True):
def request(self, endpoint, payload=None, result_is_json=True, result_is_list=True):
url = self.service_url + endpoint
auth = (self.username, self.password)
headers = {}
if result_is_json:
headers['Accept'] = 'application/json'
if payload is None:
result = self.requests.get(url, auth=auth, headers=headers)
response = self.requests.get(url, auth=auth, headers=headers)
else:
headers['Content-Type'] = 'application/json'
data = json.dumps(payload)
result = self.requests.post(url, data=data, auth=auth, headers=headers)
if result.status_code in (401, 403):
raise APIError(result.json()['message'], http_status=500)
if result_is_json:
return result.json()
else:
return result
response = self.requests.post(url, data=data, auth=auth, headers=headers)
if not result_is_json:
if response.status_code // 100 != 2:
try:
data = response.json()
except ValueError:
data = {'message': 'HTTP request failed'}
raise APIError('%s (HTTP error %s)' % (data.get('message'), response.status_code), data=data)
return response
try:
data = response.json()
except ValueError:
raise APIError('bad JSON response: %r' % response.content)
if response.status_code in (401, 403):
raise APIError('%s (%s)' % (data.get('message'), response.status_code), data=data)
if result_is_list and not isinstance(data, list):
raise APIError('response is not a list', data=data)
if response.status_code // 100 != 2:
data = {
'status_code': response.status_code,
'payload': data,
}
raise APIError('HTTP request failed, error %s' % response.status_code, data=data)
return data
@endpoint()
def cities(self, request):
@ -178,12 +195,12 @@ class Okina(BaseResource):
raise APIError('payload must be a JSON object', http_status=400)
if not isinstance(payload, dict):
raise APIError('payload must be a dict', http_status=400)
return {'data': self.request('subscribers', payload)}
return {'data': self.request('subscribers', payload, result_is_list=False)}
@endpoint(name='subscriber', pattern='^(?P<subscriber_id>\d+)/*$',
methods=['get'], perm='can_access')
def get_subscriber(self, request, subscriber_id):
return {'data': self.request('subscribers/%s' % subscriber_id)}
return {'data': self.request('subscribers/%s' % subscriber_id, result_is_list=False)}
@endpoint(name='subscriber', pattern='^(?P<subscriber_id>\d+)/qrcode/*$',
perm='can_access')
@ -205,9 +222,9 @@ class Okina(BaseResource):
raise APIError('payload must be a JSON object', http_status=400)
if not isinstance(payload, dict):
raise APIError('payload must be a dict', http_status=400)
return {'data': self.request('subscriptions', payload)}
return {'data': self.request('subscriptions', payload, result_is_list=False)}
@endpoint(name='subscription', pattern='^(?P<subscription_id>\d+)/*$',
methods=['get'], perm='can_access')
def get_subscription(self, request, subscription_id):
return {'data': self.request('subscriptions/%s' % subscription_id)}
return {'data': self.request('subscriptions/%s' % subscription_id, result_is_list=False)}

View File

@ -1506,22 +1506,24 @@ def test_okina_errors(app, okina):
(200, '<h1>Welcome</h1>'), # bad json
(403, '<h1>Bad creds</h1>'),
(404, '<h1>Not Found</h1>'),
(400, '{"message": "bad request"}'),
(400, '[{"message": "bad request"}]'),
(500, '<h1>Crash</h1>'),
):
requests_get.return_value = utils.FakedResponse(content=response[1],
status_code=response[0])
resp = app.get('/okina/test/cities', status=500)
resp = app.get('/okina/test/cities', status=200)
assert resp.json['err'] == 1
assert resp.json['data'] == None
if resp.json['data'] and 'status_code' in resp.json['data']:
assert resp.json['data']['status_code'] == response[0]
# "normal" 401/403 response, ie problem with login/password
for status_code in (401, 403):
requests_get.return_value = utils.FakedResponse(content='''{"message": "Invalid credentials",
"code": 4, "status" : %d}''' % status_code, status_code=status_code)
resp = app.get('/okina/test/cities', status=500)
resp = app.get('/okina/test/cities', status=200)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == "Invalid credentials"
assert resp.json['data'] is None
assert resp.json['err_desc'].startswith("Invalid credentials")
def test_okina_suscribe(app, okina):
@ -1574,23 +1576,15 @@ def test_okina_suscribe(app, okina):
requests_get.return_value = utils.FakedResponse(content=QRCODE_400,
headers={'Content-Type': 'application/json' },
status_code=400)
resp = app.get(endpoint, status=400)
resp = app.get(endpoint, status=200)
assert requests_get.call_count == 2
assert resp.json == {
u'err': 1,
u'err_class': u'passerelle.utils.jsonresponse.APIError',
u'err_desc': u'Subscriber with ID 123 has no passcard number to generate qr code from.',
u'data': None,
}
assert resp.json['err'] == 1
assert resp.json['err_desc'].startswith('Subscriber with ID 123 has no passcard number to generate qr code from.')
requests_get.return_value = utils.FakedResponse(content=QRCODE_404,
headers={'Content-Type': 'application/json' },
status_code=404)
resp = app.get(endpoint, status=404)
resp = app.get(endpoint, status=200)
assert requests_get.call_count == 3
assert resp.json == {
u'err': 1,
u'err_class': u'passerelle.utils.jsonresponse.APIError',
u'err_desc': u'Subscriber with ID 123 not found.',
u'data': None,
}
assert resp.json['err'] == 1
assert resp.json['err_desc'].startswith('Subscriber with ID 123 not found.')