Add custom error code to ClientSideError
Added custom error status code for ClientSideError exception instead of hardcoded value 400. Fixed case when user exception with client error code formatted as server error. Pecan extension fixed. Change-Id: I2663db0aa88538b722eb2783d130585b0fc2335b
This commit is contained in:
parent
a84d744794
commit
9546c10250
@ -94,6 +94,9 @@ class AuthorsController(RestController):
|
||||
if id == 997:
|
||||
raise NonHttpException(id)
|
||||
|
||||
if id == 996:
|
||||
raise wsme.exc.ClientSideError('Disabled ID', status_code=403)
|
||||
|
||||
if id == 911:
|
||||
return wsme.api.Response(Author(),
|
||||
status_code=401)
|
||||
|
@ -5,7 +5,7 @@ import pecan
|
||||
import six
|
||||
|
||||
|
||||
used_status_codes = [400, 401, 404, 500]
|
||||
used_status_codes = [400, 401, 403, 404, 500]
|
||||
http_response_messages = {}
|
||||
for code in used_status_codes:
|
||||
http_response_messages[code] = '%s %s' % (code, http_client.responses[code])
|
||||
@ -96,14 +96,14 @@ class TestWS(FunctionalTest):
|
||||
)
|
||||
self.assertEqual(res.status, expected_status)
|
||||
a = json.loads(res.body.decode('utf-8'))
|
||||
assert a['faultcode'] == 'Server'
|
||||
assert a['faultcode'] == 'Client'
|
||||
|
||||
res = self.app.get(
|
||||
'/authors/998.xml',
|
||||
expect_errors=True
|
||||
)
|
||||
self.assertEqual(res.status, expected_status)
|
||||
assert '<faultcode>Server</faultcode>' in res.body.decode('utf-8')
|
||||
assert '<faultcode>Client</faultcode>' in res.body.decode('utf-8')
|
||||
|
||||
def test_custom_non_http_clientside_error(self):
|
||||
expected_status_code = 500
|
||||
@ -123,6 +123,24 @@ class TestWS(FunctionalTest):
|
||||
self.assertEqual(res.status, expected_status)
|
||||
assert '<faultcode>Server</faultcode>' in res.body.decode('utf-8')
|
||||
|
||||
def test_clientsideerror_status_code(self):
|
||||
expected_status_code = 403
|
||||
expected_status = http_response_messages[expected_status_code]
|
||||
res = self.app.get(
|
||||
'/authors/996.json',
|
||||
expect_errors=True
|
||||
)
|
||||
self.assertEqual(res.status, expected_status)
|
||||
a = json.loads(res.body.decode('utf-8'))
|
||||
assert a['faultcode'] == 'Client'
|
||||
|
||||
res = self.app.get(
|
||||
'/authors/996.xml',
|
||||
expect_errors=True
|
||||
)
|
||||
self.assertEqual(res.status, expected_status)
|
||||
assert '<faultcode>Client</faultcode>' in res.body.decode('utf-8')
|
||||
|
||||
def test_non_default_response(self):
|
||||
expected_status_code = 401
|
||||
expected_status = http_response_messages[expected_status_code]
|
||||
|
@ -181,5 +181,5 @@ class WSMECorniceTestCase(unittest.TestCase):
|
||||
expect_errors=True
|
||||
)
|
||||
print resp.body
|
||||
self.assertEquals(resp.json['faultcode'], 'Server')
|
||||
self.assertEquals(resp.json['faultcode'], 'Client')
|
||||
self.assertEquals(resp.status_code, 401)
|
||||
|
@ -138,7 +138,7 @@ class FlaskrTestCase(unittest.TestCase):
|
||||
headers={'Accept': 'application/xml'}
|
||||
)
|
||||
assert r.status_code == 403, r.status_code
|
||||
assert r.data == ('<error><faultcode>Server</faultcode>'
|
||||
assert r.data == ('<error><faultcode>Client</faultcode>'
|
||||
'<faultstring>403: Forbidden</faultstring>'
|
||||
'<debuginfo /></error>')
|
||||
|
||||
@ -155,7 +155,7 @@ class FlaskrTestCase(unittest.TestCase):
|
||||
headers={'Accept': 'application/xml'}
|
||||
)
|
||||
assert r.status_code == 412, r.status_code
|
||||
assert r.data == ('<error><faultcode>Server</faultcode>'
|
||||
assert r.data == ('<error><faultcode>Client</faultcode>'
|
||||
'<faultstring>FOO!</faultstring>'
|
||||
'<debuginfo /></error>')
|
||||
|
||||
|
@ -109,7 +109,7 @@ class TestController(testutil.TGTest):
|
||||
assert response.status_int == 400
|
||||
assert simplejson.loads(response.body) == {
|
||||
"debuginfo": None,
|
||||
"faultcode": "Server",
|
||||
"faultcode": "Client",
|
||||
"faultstring": "(400, 'Cannot divide by zero!')"
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ class TestController(testutil.TGTest):
|
||||
expect_errors=True
|
||||
)
|
||||
assert response.status_int == 400
|
||||
assert response.body == ("<error><faultcode>Server</faultcode>"
|
||||
assert response.body == ("<error><faultcode>Client</faultcode>"
|
||||
"<faultstring>(400, 'Cannot divide by zero!')"
|
||||
"</faultstring><debuginfo /></error>")
|
||||
|
||||
|
@ -6,6 +6,8 @@ import logging
|
||||
import wsme.exc
|
||||
import wsme.types
|
||||
|
||||
from wsme import utils
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -200,9 +202,12 @@ class Response(object):
|
||||
def format_exception(excinfo, debug=False):
|
||||
"""Extract informations that can be sent to the client."""
|
||||
error = excinfo[1]
|
||||
if isinstance(error, wsme.exc.ClientSideError):
|
||||
code = getattr(error, 'code', None)
|
||||
if code and utils.is_valid_code(code) and utils.is_client_error(code):
|
||||
faultstring = error.faultstring if hasattr(error, 'faultstring') \
|
||||
else str(error)
|
||||
r = dict(faultcode="Client",
|
||||
faultstring=error.faultstring)
|
||||
faultstring=faultstring)
|
||||
log.warning("Client-side error: %s" % r['faultstring'])
|
||||
r['debuginfo'] = None
|
||||
return r
|
||||
|
@ -4,8 +4,9 @@ from wsme.utils import _
|
||||
|
||||
|
||||
class ClientSideError(RuntimeError):
|
||||
def __init__(self, msg=None):
|
||||
def __init__(self, msg=None, status_code=400):
|
||||
self.msg = msg
|
||||
self.code = status_code
|
||||
super(ClientSideError, self).__init__(self.faultstring)
|
||||
|
||||
@property
|
||||
|
@ -1,7 +1,7 @@
|
||||
import datetime
|
||||
import unittest
|
||||
|
||||
from wsme.utils import parse_isodate, parse_isotime, parse_isodatetime
|
||||
from wsme import utils
|
||||
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
@ -18,9 +18,9 @@ class TestUtils(unittest.TestCase):
|
||||
'2012-02-30',
|
||||
]
|
||||
for s, d in good_dates:
|
||||
assert parse_isodate(s) == d
|
||||
assert utils.parse_isodate(s) == d
|
||||
for s in ill_formatted_dates + out_of_range_dates:
|
||||
self.assertRaises(ValueError, parse_isodate, s)
|
||||
self.assertRaises(ValueError, utils.parse_isodate, s)
|
||||
|
||||
def test_parse_isotime(self):
|
||||
good_times = [
|
||||
@ -35,9 +35,9 @@ class TestUtils(unittest.TestCase):
|
||||
'00:54:60',
|
||||
]
|
||||
for s, t in good_times:
|
||||
assert parse_isotime(s) == t
|
||||
assert utils.parse_isotime(s) == t
|
||||
for s in ill_formatted_times + out_of_range_times:
|
||||
self.assertRaises(ValueError, parse_isotime, s)
|
||||
self.assertRaises(ValueError, utils.parse_isotime, s)
|
||||
|
||||
def test_parse_isodatetime(self):
|
||||
good_datetimes = [
|
||||
@ -54,6 +54,27 @@ class TestUtils(unittest.TestCase):
|
||||
'2012-13-12T00:54:60',
|
||||
]
|
||||
for s, t in good_datetimes:
|
||||
assert parse_isodatetime(s) == t
|
||||
assert utils.parse_isodatetime(s) == t
|
||||
for s in ill_formatted_datetimes + out_of_range_datetimes:
|
||||
self.assertRaises(ValueError, parse_isodatetime, s)
|
||||
self.assertRaises(ValueError, utils.parse_isodatetime, s)
|
||||
|
||||
def test_validator_with_valid_code(self):
|
||||
valid_code = 404
|
||||
assert (
|
||||
utils.is_valid_code(valid_code),
|
||||
"Valid status code not detected"
|
||||
)
|
||||
|
||||
def test_validator_with_invalid_int_code(self):
|
||||
invalid_int_code = 648
|
||||
assert (
|
||||
not utils.is_valid_code(invalid_int_code),
|
||||
"Invalid status code not detected"
|
||||
)
|
||||
|
||||
def test_validator_with_invalid_str_code(self):
|
||||
invalid_str_code = '404'
|
||||
assert (
|
||||
not utils.is_valid_code(invalid_str_code),
|
||||
"Invalid status code not detected"
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import decimal
|
||||
import datetime
|
||||
import re
|
||||
from six.moves import builtins
|
||||
from six.moves import builtins, http_client
|
||||
|
||||
try:
|
||||
import dateutil.parser
|
||||
@ -84,6 +84,18 @@ def parse_isodatetime(value):
|
||||
raise ValueError("'%s' is a out-of-range datetime" % (value))
|
||||
|
||||
|
||||
def is_valid_code(code_value):
|
||||
"""
|
||||
This function checks if incoming value in http response codes range.
|
||||
"""
|
||||
return code_value in http_client.responses
|
||||
|
||||
|
||||
def is_client_error(code):
|
||||
""" Checks client error code (RFC 2616)."""
|
||||
return 400 <= code < 500
|
||||
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
|
@ -9,7 +9,7 @@ import wsme.api
|
||||
import wsme.rest.json
|
||||
import wsme.rest.xml
|
||||
import wsme.rest.args
|
||||
from wsmeext.utils import is_valid_code
|
||||
from wsme.utils import is_valid_code
|
||||
|
||||
import flask
|
||||
|
||||
|
@ -11,7 +11,7 @@ import wsme.rest.xml
|
||||
|
||||
import pecan
|
||||
|
||||
from wsmeext.utils import is_valid_code
|
||||
from wsme.utils import is_valid_code
|
||||
|
||||
|
||||
class JSonRenderer(object):
|
||||
@ -94,9 +94,7 @@ def wsexpose(*args, **kwargs):
|
||||
finally:
|
||||
del exception_info
|
||||
|
||||
if data['faultcode'] == 'Client':
|
||||
pecan.response.status = 400
|
||||
elif orig_code and is_valid_code(orig_code):
|
||||
if orig_code and is_valid_code(orig_code):
|
||||
pecan.response.status = orig_code
|
||||
else:
|
||||
pecan.response.status = 500
|
||||
|
@ -1,22 +0,0 @@
|
||||
from wsmeext.utils import is_valid_code
|
||||
|
||||
|
||||
class TestUtils():
|
||||
|
||||
def test_validator_with_valid_code(self):
|
||||
valid_code = 404
|
||||
assert is_valid_code(valid_code), "Valid status code not detected"
|
||||
|
||||
def test_validator_with_invalid_int_code(self):
|
||||
invalid_int_code = 648
|
||||
assert (
|
||||
not is_valid_code(invalid_int_code),
|
||||
"Invalid status code not detected"
|
||||
)
|
||||
|
||||
def test_validator_with_invalid_str_code(self):
|
||||
invalid_str_code = '404'
|
||||
assert (
|
||||
not is_valid_code(invalid_str_code),
|
||||
"Invalid status code not detected"
|
||||
)
|
@ -14,7 +14,7 @@ from wsme.rest import validate as wsvalidate
|
||||
import wsme.api
|
||||
import wsme.rest.args
|
||||
import wsme.rest.json
|
||||
from wsmeext.utils import is_valid_code
|
||||
from wsme.utils import is_valid_code
|
||||
|
||||
import inspect
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
"""
|
||||
This File consists of utils functions used in wsmeext module.
|
||||
"""
|
||||
from six.moves import http_client
|
||||
|
||||
|
||||
def is_valid_code(code_value):
|
||||
"""
|
||||
This function checks if incoming value in http response codes range.
|
||||
"""
|
||||
return code_value in http_client.responses
|
Loading…
Reference in New Issue
Block a user