diff --git a/.gitignore b/.gitignore
index 96b9edf..ba5f335 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,5 @@ dist
doc/_build
d2to1-*.egg
+
+WSME.egg-info/
diff --git a/tests/pecantest/test/controllers/ws.py b/tests/pecantest/test/controllers/ws.py
index cddaec0..f0dcba4 100644
--- a/tests/pecantest/test/controllers/ws.py
+++ b/tests/pecantest/test/controllers/ws.py
@@ -19,6 +19,24 @@ class Book(Base):
author = wsattr('Author')
+class BookNotFound(Exception):
+ message = "Book with ID={id} Not Found"
+ code = 404
+
+ def __init__(self, id):
+ message = self.message.format(id=id)
+ super(BookNotFound, self).__init__(message)
+
+
+class NonHttpException(Exception):
+ message = "Internal Exception for Book ID={id}"
+ code = 684
+
+ def __init__(self, id):
+ message = self.message.format(id=id)
+ super(NonHttpException, self).__init__(message)
+
+
class BooksController(RestController):
@wsmeext.pecan.wsexpose(Book, int, int)
@@ -71,6 +89,12 @@ class AuthorsController(RestController):
if id == 999:
raise wsme.exc.ClientSideError('Wrong ID')
+ if id == 998:
+ raise BookNotFound(id)
+
+ if id == 997:
+ raise NonHttpException(id)
+
if id == 911:
return wsme.api.Response(Author(),
status_code=401)
diff --git a/tests/pecantest/test/tests/test_ws.py b/tests/pecantest/test/tests/test_ws.py
index bd5c704..3c22042 100644
--- a/tests/pecantest/test/tests/test_ws.py
+++ b/tests/pecantest/test/tests/test_ws.py
@@ -1,7 +1,15 @@
+from six.moves import http_client
from test.tests import FunctionalTest
import json
import pecan
+used_status_codes = [400, 401, 404, 500]
+http_response_messages = {
+ code: '{} {}'.format(code, status)
+ for code, status in http_client.responses.iteritems()
+ if code in used_status_codes
+}
+
class TestWS(FunctionalTest):
@@ -70,12 +78,14 @@ class TestWS(FunctionalTest):
assert a['firstname'] == 'test'
def test_clientsideerror(self):
+ expected_status_code = 400
+ expected_status = http_response_messages[expected_status_code]
res = self.app.get(
'/authors/999.json',
expect_errors=True
)
print res
- self.assertEqual(res.status, '400 Bad Request')
+ self.assertEqual(res.status, expected_status)
a = json.loads(res.body)
print a
assert a['faultcode'] == 'Client'
@@ -85,29 +95,77 @@ class TestWS(FunctionalTest):
expect_errors=True
)
print res
- self.assertEqual(res.status, '400 Bad Request')
+ self.assertEqual(res.status, expected_status)
assert 'Client' in res.body
+ def test_custom_clientside_error(self):
+ expected_status_code = 404
+ expected_status = http_response_messages[expected_status_code]
+ res = self.app.get(
+ '/authors/998.json',
+ expect_errors=True
+ )
+ print res
+ self.assertEqual(res.status, expected_status)
+ a = json.loads(res.body)
+ print a
+ assert a['faultcode'] == 'Server'
+
+ res = self.app.get(
+ '/authors/998.xml',
+ expect_errors=True
+ )
+ print res
+ self.assertEqual(res.status, expected_status)
+ assert 'Server' in res.body
+
+ def test_custom_non_http_clientside_error(self):
+ expected_status_code = 500
+ expected_status = http_response_messages[expected_status_code]
+ res = self.app.get(
+ '/authors/997.json',
+ expect_errors=True
+ )
+ print res
+ self.assertEqual(res.status, expected_status)
+ a = json.loads(res.body)
+ print a
+ assert a['faultcode'] == 'Server'
+
+ res = self.app.get(
+ '/authors/997.xml',
+ expect_errors=True
+ )
+ print res
+ self.assertEqual(res.status, expected_status)
+ assert 'Server' in res.body
+
def test_non_default_response(self):
+ expected_status_code = 401
+ expected_status = http_response_messages[expected_status_code]
res = self.app.get(
'/authors/911.json',
expect_errors=True
)
- self.assertEqual(res.status_int, 401)
- self.assertEqual(res.status, '401 Unauthorized')
+ self.assertEqual(res.status_int, expected_status_code)
+ self.assertEqual(res.status, expected_status)
def test_serversideerror(self):
+ expected_status_code = 500
+ expected_status = http_response_messages[expected_status_code]
res = self.app.get('/divide_by_zero.json', expect_errors=True)
- self.assertEqual(res.status, '500 Internal Server Error')
+ self.assertEqual(res.status, expected_status)
a = json.loads(res.body)
print a
assert a['faultcode'] == 'Server'
assert a['debuginfo'] is None
def test_serversideerror_with_debug(self):
+ expected_status_code = 500
+ expected_status = http_response_messages[expected_status_code]
pecan.set_config({'wsme': {'debug': True}})
res = self.app.get('/divide_by_zero.json', expect_errors=True)
- self.assertEqual(res.status, '500 Internal Server Error')
+ self.assertEqual(res.status, expected_status)
a = json.loads(res.body)
print a
assert a['faultcode'] == 'Server'
diff --git a/wsmeext/pecan.py b/wsmeext/pecan.py
index f8390b0..268c76c 100644
--- a/wsmeext/pecan.py
+++ b/wsmeext/pecan.py
@@ -11,6 +11,8 @@ import wsme.rest.xml
import pecan
+from wsmeext.utils import is_valid_code
+
class JSonRenderer(object):
def __init__(self, path, extra_vars):
@@ -76,14 +78,24 @@ def wsexpose(*args, **kwargs):
result = result.obj
except:
- data = wsme.api.format_exception(
- sys.exc_info(),
- pecan.conf.get('wsme', {}).get('debug', False)
- )
+ try:
+ exception_info = sys.exc_info()
+ orig_exception = exception_info[1]
+ orig_code = getattr(orig_exception, 'code', None)
+ data = wsme.api.format_exception(
+ exception_info,
+ pecan.conf.get('wsme', {}).get('debug', False)
+ )
+ finally:
+ del exception_info
+
if data['faultcode'] == 'Client':
pecan.response.status = 400
+ elif orig_code and is_valid_code(orig_code):
+ pecan.response.status = orig_code
else:
pecan.response.status = 500
+
return data
if funcdef.return_type is None:
diff --git a/wsmeext/tests/test_utils.py b/wsmeext/tests/test_utils.py
new file mode 100644
index 0000000..383a394
--- /dev/null
+++ b/wsmeext/tests/test_utils.py
@@ -0,0 +1,16 @@
+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"
\ No newline at end of file
diff --git a/wsmeext/utils.py b/wsmeext/utils.py
new file mode 100644
index 0000000..58b4013
--- /dev/null
+++ b/wsmeext/utils.py
@@ -0,0 +1,11 @@
+"""
+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