Add improved support for HTTP response codes in TG 1.x apps.

Change-Id: I829ab360e13ae88a47e810079c739eac1d925139
This commit is contained in:
Ryan Petrello 2013-09-06 15:06:35 -04:00
parent d8a70a300e
commit 0aba00b1ef
3 changed files with 98 additions and 5 deletions

View File

@ -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 == "<result>50</result>"
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 == ("<error><faultcode>Server</faultcode>"
"<faultstring>(400, 'Cannot divide by zero!')"
"</faultstring><debuginfo /></error>")
def test_soap_wsdl(self):
ts = test_soap.TestSOAP('test_wsdl')
ts.app = self.app

View File

@ -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 == "<result>50</result>"
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 == ("<error><faultcode>Server</faultcode>"
"<faultstring>(400, 'Cannot divide by zero!')"
"</faultstring><debuginfo /></error>")
def test_soap_wsdl(self):
wsdl = self.app.get('/ws/api.wsdl').body
print wsdl

View File

@ -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