adding easily overrideable error_handler method to Resource and test case
This commit is contained in:
Родитель
2f1e34f43b
Коммит
267a1bd2cf
|
@ -162,52 +162,9 @@ class Resource(object):
|
|||
|
||||
try:
|
||||
result = meth(request, *args, **kwargs)
|
||||
except FormValidationError, e:
|
||||
return self.form_validation_response(e)
|
||||
except TypeError, e:
|
||||
result = rc.BAD_REQUEST
|
||||
hm = HandlerMethod(meth)
|
||||
sig = hm.signature
|
||||
|
||||
msg = 'Method signature does not match.\n\n'
|
||||
|
||||
if sig:
|
||||
msg += 'Signature should be: %s' % sig
|
||||
else:
|
||||
msg += 'Resource does not expect any parameters.'
|
||||
|
||||
if self.display_errors:
|
||||
msg += '\n\nException was: %s' % str(e)
|
||||
|
||||
result.content = format_error(msg)
|
||||
except Http404:
|
||||
return rc.NOT_FOUND
|
||||
except HttpStatusCode, e:
|
||||
return e.response
|
||||
except Exception, e:
|
||||
"""
|
||||
On errors (like code errors), we'd like to be able to
|
||||
give crash reports to both admins and also the calling
|
||||
user. There's two setting parameters for this:
|
||||
result = self.error_handler(e, request)
|
||||
|
||||
Parameters::
|
||||
- `PISTON_EMAIL_ERRORS`: Will send a Django formatted
|
||||
error email to people in `settings.ADMINS`.
|
||||
- `PISTON_DISPLAY_ERRORS`: Will return a simple traceback
|
||||
to the caller, so he can tell you what error they got.
|
||||
|
||||
If `PISTON_DISPLAY_ERRORS` is not enabled, the caller will
|
||||
receive a basic "500 Internal Server Error" message.
|
||||
"""
|
||||
exc_type, exc_value, tb = sys.exc_info()
|
||||
rep = ExceptionReporter(request, exc_type, exc_value, tb.tb_next)
|
||||
if self.email_errors:
|
||||
self.email_exception(rep)
|
||||
if self.display_errors:
|
||||
return HttpResponseServerError(
|
||||
format_error('\n'.join(rep.format_exception())))
|
||||
else:
|
||||
raise
|
||||
|
||||
emitter, ct = Emitter.get(em_format)
|
||||
fields = handler.fields
|
||||
|
@ -282,3 +239,59 @@ class Resource(object):
|
|||
|
||||
message.content_subtype = 'html'
|
||||
message.send(fail_silently=True)
|
||||
|
||||
|
||||
def error_handler(self, e, request):
|
||||
"""
|
||||
Override this method add handling of errors customized for your
|
||||
needs
|
||||
"""
|
||||
if isinstance(e, FormValidationError):
|
||||
return self.form_validation_response(e)
|
||||
|
||||
elif isinstance(e, TypeError):
|
||||
result = rc.BAD_REQUEST
|
||||
hm = HandlerMethod(meth)
|
||||
sig = hm.signature
|
||||
|
||||
msg = 'Method signature does not match.\n\n'
|
||||
|
||||
if sig:
|
||||
msg += 'Signature should be: %s' % sig
|
||||
else:
|
||||
msg += 'Resource does not expect any parameters.'
|
||||
|
||||
if self.display_errors:
|
||||
msg += '\n\nException was: %s' % str(e)
|
||||
|
||||
result.content = format_error(msg)
|
||||
elif isinstance(e, Http404):
|
||||
return rc.NOT_FOUND
|
||||
|
||||
elif isinstance(e, HttpStatusCode):
|
||||
return e.response
|
||||
|
||||
else:
|
||||
"""
|
||||
On errors (like code errors), we'd like to be able to
|
||||
give crash reports to both admins and also the calling
|
||||
user. There's two setting parameters for this:
|
||||
|
||||
Parameters::
|
||||
- `PISTON_EMAIL_ERRORS`: Will send a Django formatted
|
||||
error email to people in `settings.ADMINS`.
|
||||
- `PISTON_DISPLAY_ERRORS`: Will return a simple traceback
|
||||
to the caller, so he can tell you what error they got.
|
||||
|
||||
If `PISTON_DISPLAY_ERRORS` is not enabled, the caller will
|
||||
receive a basic "500 Internal Server Error" message.
|
||||
"""
|
||||
exc_type, exc_value, tb = sys.exc_info()
|
||||
rep = ExceptionReporter(request, exc_type, exc_value, tb.tb_next)
|
||||
if self.email_errors:
|
||||
self.email_exception(rep)
|
||||
if self.display_errors:
|
||||
return HttpResponseServerError(
|
||||
format_error('\n'.join(rep.format_exception())))
|
||||
else:
|
||||
raise
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from django.core import mail
|
||||
from django.contrib.auth.models import User
|
||||
from django.conf import settings
|
||||
from django.http import HttpRequest
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils import simplejson
|
||||
|
||||
# Piston imports
|
||||
|
@ -81,3 +81,56 @@ class CustomResponseWithStatusCodeTest(TestCase):
|
|||
# compare the original data dict with the json response
|
||||
# converted to a dict
|
||||
self.assertEquals(response_data, simplejson.loads(response.content))
|
||||
|
||||
|
||||
class ErrorHandlerTest(TestCase):
|
||||
def test_customized_error_handler(self):
|
||||
"""
|
||||
Throw a custom error from a handler method and catch (and format) it
|
||||
in an overridden error_handler method on the associated Resource object
|
||||
"""
|
||||
class GoAwayError(Exception):
|
||||
def __init__(self, name, reason):
|
||||
self.name = name
|
||||
self.reason = reason
|
||||
|
||||
class MyHandler(BaseHandler):
|
||||
"""
|
||||
Handler which raises a custom exception
|
||||
"""
|
||||
def read(self, request):
|
||||
raise GoAwayError('Jerome', 'No one likes you')
|
||||
|
||||
class MyResource(Resource):
|
||||
def error_handler(self, error, request):
|
||||
# if the exeption is our exeption then generate a
|
||||
# custom response with embedded content that will be
|
||||
# formatted as json
|
||||
if isinstance(error, GoAwayError):
|
||||
response = rc.FORBIDDEN
|
||||
response.content = dict(error=dict(
|
||||
name=error.name,
|
||||
message="Get out of here and dont come back",
|
||||
reason=error.reason
|
||||
))
|
||||
|
||||
return response
|
||||
|
||||
return super(error_handler, self).error_handler(error, request)
|
||||
|
||||
resource = MyResource(MyHandler)
|
||||
|
||||
request = HttpRequest()
|
||||
request.method = 'GET'
|
||||
response = resource(request, emitter_format='json')
|
||||
|
||||
self.assertEquals(401, response.status_code)
|
||||
|
||||
# verify the content we got back can be converted back to json
|
||||
# and examine the dictionary keys all exist as expected
|
||||
response_data = simplejson.loads(response.content)
|
||||
self.assertTrue('error' in response_data)
|
||||
self.assertTrue('name' in response_data['error'])
|
||||
self.assertTrue('message' in response_data['error'])
|
||||
self.assertTrue('reason' in response_data['error'])
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче