adding easily overrideable error_handler method to Resource and test case

This commit is contained in:
Matt Cordes 2010-04-12 11:44:37 -04:00
Родитель 2f1e34f43b
Коммит 267a1bd2cf
2 изменённых файлов: 111 добавлений и 45 удалений

Просмотреть файл

@ -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'])