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 import wsmeext.tg1
from turbogears.controllers import RootController from turbogears.controllers import RootController
import cherrypy
import unittest import unittest
@ -43,9 +44,14 @@ class Root(RootController):
def multiply(self, a, b): def multiply(self, a, b):
return 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 from turbogears import testutil, config, startup
@ -108,6 +114,31 @@ class TestController(unittest.TestCase):
print response print response
assert response.body == "<result>50</result>" 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): def test_soap_wsdl(self):
ts = test_soap.TestSOAP('test_wsdl') ts = test_soap.TestSOAP('test_wsdl')
ts.app = self.app ts.app = self.app

View File

@ -2,6 +2,7 @@ import wsmeext.tg15
from wsme import WSRoot from wsme import WSRoot
from turbogears.controllers import RootController from turbogears.controllers import RootController
import cherrypy
from wsmeext.tests import test_soap from wsmeext.tests import test_soap
@ -35,6 +36,13 @@ class Root(RootController):
def multiply(self, a, b): def multiply(self, a, b):
return 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 from turbogears import testutil
@ -91,6 +99,31 @@ class TestController(testutil.TGTest):
print response print response
assert response.body == "<result>50</result>" 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): def test_soap_wsdl(self):
wsdl = self.app.get('/ws/api.wsdl').body wsdl = self.app.get('/ws/api.wsdl').body
print wsdl print wsdl

View File

@ -4,15 +4,17 @@ except ImportError:
import simplejson as json # noqa import simplejson as json # noqa
import functools import functools
import sys
import cherrypy import cherrypy
import webob import webob
from turbogears import expose from turbogears import expose, util
from wsme.rest import validate as wsvalidate from wsme.rest import validate as wsvalidate
import wsme.api import wsme.api
import wsme.rest.args import wsme.rest.args
import wsme.rest.json import wsme.rest.json
from wsmeext.utils import is_valid_code
import inspect import inspect
@ -55,7 +57,35 @@ def wsexpose(*args, **kwargs):
) )
if funcdef.pass_request: if funcdef.pass_request:
kwargs[funcdef.pass_request] = cherrypy.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( return dict(
datatype=funcdef.return_type, datatype=funcdef.return_type,
result=result result=result
@ -116,7 +146,6 @@ class Controller(object):
cherrypy.response.status = res.status cherrypy.response.status = res.status
return res.body return res.body
import wsme.rest import wsme.rest