Skip to content
This repository was archived by the owner on Apr 15, 2024. It is now read-only.

Commit 53bb888

Browse files
committed
Manage additional 4xx HTTP status code #186
1 parent 596cdce commit 53bb888

File tree

2 files changed

+66
-12
lines changed

2 files changed

+66
-12
lines changed

consul/base.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ class BadRequest(ConsulException):
3636
pass
3737

3838

39+
class ClientError(ConsulException):
40+
"""Encapsulates 4xx Http error code"""
41+
pass
42+
43+
3944
#
4045
# Convenience to define checks
4146

@@ -158,24 +163,28 @@ def _compat(
158163

159164
class CB(object):
160165
@classmethod
161-
def __status(klass, response, allow_404=True):
166+
def _status(klass, response, allow_404=True):
162167
# status checking
163-
if response.code >= 500 and response.code < 600:
168+
if 400 <= response.code < 500:
169+
if response.code == 400:
170+
raise BadRequest('%d %s' % (response.code, response.body))
171+
elif response.code == 401:
172+
raise ACLDisabled(response.body)
173+
elif response.code == 403:
174+
raise ACLPermissionDenied(response.body)
175+
elif response.code == 404:
176+
if not allow_404:
177+
raise NotFound(response.body)
178+
else:
179+
raise ClientError("%d %s" % (response.code, response.body))
180+
elif 500 <= response.code < 600:
164181
raise ConsulException("%d %s" % (response.code, response.body))
165-
if response.code == 400:
166-
raise BadRequest('%d %s' % (response.code, response.body))
167-
if response.code == 401:
168-
raise ACLDisabled(response.body)
169-
if response.code == 403:
170-
raise ACLPermissionDenied(response.body)
171-
if response.code == 404 and not allow_404:
172-
raise NotFound(response.body)
173182

174183
@classmethod
175184
def bool(klass):
176185
# returns True on successful response
177186
def cb(response):
178-
CB.__status(response)
187+
CB._status(response)
179188
return response.code == 200
180189
return cb
181190

@@ -204,7 +213,7 @@ def json(
204213
*is_id* only the 'ID' field of the json object will be returned.
205214
"""
206215
def cb(response):
207-
CB.__status(response, allow_404=allow_404)
216+
CB._status(response, allow_404=allow_404)
208217
if response.code == 404:
209218
return response.headers['X-Consul-Index'], None
210219

tests/test_base.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import consul.base
66

77

8+
CB = consul.base.CB
9+
Response = consul.base.Response
10+
811
Request = collections.namedtuple(
912
'Request', ['method', 'path', 'params', 'data'])
1013

@@ -77,6 +80,48 @@ def test_implicit(self):
7780
assert r(consistency='stale').params == {'stale': '1'}
7881

7982

83+
class TestCB(object):
84+
85+
def test_status_200_passes(self):
86+
response = consul.base.Response(200, None, None)
87+
CB._status(response)
88+
89+
@pytest.mark.parametrize(
90+
'response, expected_exception',
91+
[
92+
(Response(400, None, None), consul.base.BadRequest),
93+
(Response(401, None, None), consul.base.ACLDisabled),
94+
(Response(403, None, None), consul.base.ACLPermissionDenied),
95+
])
96+
def test_status_4xx_raises_error(self, response, expected_exception):
97+
with pytest.raises(expected_exception):
98+
CB._status(response)
99+
100+
def test_status_404_allow_404(self):
101+
response = Response(404, None, None)
102+
CB._status(response, allow_404=True)
103+
104+
def test_status_404_dont_allow_404(self):
105+
response = Response(404, None, None)
106+
with pytest.raises(consul.base.NotFound):
107+
CB._status(response, allow_404=False)
108+
109+
def test_status_405_raises_generic_ClientError(self):
110+
response = Response(405, None, None)
111+
with pytest.raises(consul.base.ClientError):
112+
CB._status(response)
113+
114+
@pytest.mark.parametrize(
115+
'response',
116+
[
117+
Response(500, None, None),
118+
Response(599, None, None),
119+
])
120+
def test_status_5xx_raises_error(self, response):
121+
with pytest.raises(consul.base.ConsulException):
122+
CB._status(response)
123+
124+
80125
class TestChecks(object):
81126
"""
82127
Check constructor helpers return valid check configurations.

0 commit comments

Comments
 (0)