diff --git a/tests/test_tg1.py b/tests/test_tg1.py index 5a4f593..f5a27a9 100644 --- a/tests/test_tg1.py +++ b/tests/test_tg1.py @@ -4,6 +4,7 @@ from wsmeext.tg11 import wsexpose, wsvalidate import wsmeext.tg1 from turbogears.controllers import RootController +import cherrypy import unittest @@ -43,9 +44,14 @@ class Root(RootController): def multiply(self, a, b): return a * b - sub = Subcontroller() + @wsexpose(int) + @wsvalidate(int, int) + def divide(self, a, b): + if b == 0: + raise cherrypy.HTTPError(400, 'Cannot divide by zero!') + return a / b -import cherrypy + sub = Subcontroller() from turbogears import testutil, config, startup @@ -108,6 +114,31 @@ class TestController(unittest.TestCase): print response assert response.body == "50" + def test_custom_clientside_error(self): + response = self.app.post( + "/divide", + simplejson.dumps({'a': 5, 'b': 0}), + {'Content-Type': 'application/json', 'Accept': 'application/json'}, + expect_errors=True + ) + assert response.status_int == 400 + assert simplejson.loads(response.body) == { + "debuginfo": None, + "faultcode": "Server", + "faultstring": "(400, 'Cannot divide by zero!')" + } + + response = self.app.post( + "/divide", + simplejson.dumps({'a': 5, 'b': 0}), + {'Content-Type': 'application/json', 'Accept': 'text/xml'}, + expect_errors=True + ) + assert response.status_int == 400 + assert response.body == ("Server" + "(400, 'Cannot divide by zero!')" + "") + def test_soap_wsdl(self): ts = test_soap.TestSOAP('test_wsdl') ts.app = self.app diff --git a/tests/test_tg15.py b/tests/test_tg15.py index 61f9127..36c6860 100644 --- a/tests/test_tg15.py +++ b/tests/test_tg15.py @@ -2,6 +2,7 @@ import wsmeext.tg15 from wsme import WSRoot from turbogears.controllers import RootController +import cherrypy from wsmeext.tests import test_soap @@ -35,6 +36,13 @@ class Root(RootController): def multiply(self, a, b): return a * b + @wsmeext.tg15.wsexpose(int) + @wsmeext.tg15.wsvalidate(int, int) + def divide(self, a, b): + if b == 0: + raise cherrypy.HTTPError(400, 'Cannot divide by zero!') + return a / b + from turbogears import testutil @@ -91,6 +99,31 @@ class TestController(testutil.TGTest): print response assert response.body == "50" + def test_custom_clientside_error(self): + response = self.app.post( + "/divide", + simplejson.dumps({'a': 5, 'b': 0}), + {'Content-Type': 'application/json', 'Accept': 'application/json'}, + expect_errors=True + ) + assert response.status_int == 400 + assert simplejson.loads(response.body) == { + "debuginfo": None, + "faultcode": "Server", + "faultstring": "(400, 'Cannot divide by zero!')" + } + + response = self.app.post( + "/divide", + simplejson.dumps({'a': 5, 'b': 0}), + {'Content-Type': 'application/json', 'Accept': 'text/xml'}, + expect_errors=True + ) + assert response.status_int == 400 + assert response.body == ("Server" + "(400, 'Cannot divide by zero!')" + "") + def test_soap_wsdl(self): wsdl = self.app.get('/ws/api.wsdl').body print wsdl diff --git a/wsmeext/tg1.py b/wsmeext/tg1.py index 70582d2..16a7bdf 100644 --- a/wsmeext/tg1.py +++ b/wsmeext/tg1.py @@ -4,15 +4,17 @@ except ImportError: import simplejson as json # noqa import functools +import sys import cherrypy import webob -from turbogears import expose +from turbogears import expose, util 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 import inspect @@ -55,7 +57,35 @@ def wsexpose(*args, **kwargs): ) if funcdef.pass_request: kwargs[funcdef.pass_request] = cherrypy.request - result = f(self, *args, **kwargs) + try: + result = f(self, *args, **kwargs) + except: + try: + exception_info = sys.exc_info() + orig_exception = exception_info[1] + if isinstance(orig_exception, cherrypy.HTTPError): + orig_code = getattr(orig_exception, 'status', None) + else: + orig_code = getattr(orig_exception, 'code', None) + data = wsme.api.format_exception(exception_info) + finally: + del exception_info + + cherrypy.response.status = 500 + if data['faultcode'] == 'client': + cherrypy.response.status = 400 + elif orig_code and is_valid_code(orig_code): + cherrypy.response.status = orig_code + + accept = cherrypy.request.headers.get('Accept', "").lower() + accept = util.simplify_http_accept_header(accept) + + decorators = {'text/xml': wsme.rest.xml.encode_error} + return decorators.get( + accept, + wsme.rest.json.encode_error + )(None, data) + return dict( datatype=funcdef.return_type, result=result @@ -116,7 +146,6 @@ class Controller(object): cherrypy.response.status = res.status return res.body - import wsme.rest