Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python/GAE web request error handling

I am developing an application on the Google App Engine using Python.

I have a handler that can return a variety of outputs (html and json at the moment), I am testing for obvious errors in the system based on invalid parameters sent to the request handler.

However what I am doing feels dirty (see below):

class FeedHandler(webapp.RequestHandler):
def get(self):
    app = self.request.get("id")
    name = self.request.get("name") 
    output_type = self.request.get("output", default_value = "html")
    pretty = self.request.get("pretty", default_value = "")


    application = model.Application.GetByKey(app)

    if application is None:
        if output_type == "json":
            self.response.out.write(simplejson.dumps({ "errorCode" : "Application not found."}))
        self.set_status(404)
        return

    category = model.FeedCategory.GetByKey(application, name)

    if category is None:
        if output_type == "json":
            self.response.out.write(simplejson.dumps({ "errorCode" : "Category not found."}))
        self.set_status(404)
        return

I am specifically handling cases per output type and also and per "assert".

I am keen to here suggestions, patterns and examples on how to clear it up (I know it is going to be a nightmare to try and maintain what I am doing).

I am toying with the idea of having and raising custom exceptions and having a decorator that will automatically work out how to display the error messages - I think it is a good idea but I am would love to get some feedback and suggestions based on how people have done this in the past.

like image 892
Kinlan Avatar asked Jan 23 '23 07:01

Kinlan


1 Answers

There's a couple of handy methods here. The first is self.error(code). By default this method simply sets the status code and clears the output buffer, but you can override it to output custom error pages depending on the error result.

The second method is self.handle__exception(exception, debug_mode). This method is called by the webapp infrastructure if any of your get/post/etc methods return an unhandled exception. By default it calls self.error(500) and logs the exception (as well as printing it to the output if debug mode is enabled). You can override this method to handle exceptions however you like. Here's an example to allow you to throw exceptions for various statuses:

class StatusCodeException(Exception):
  def __init__(self, code):
    self.status_code = code

class RedirectException(StatusCodeException):
  def __init__(self, location, status=302):
    super(RedirectException, self).__init__(status)
    self.location = location

class ForbiddenException(StatusCodeException):
  def __init__(self):
    super(ForbiddenException, self).__init__(403)

class ExtendedHandler(webapp.RequestHandler):
  def handle_exception(self, exception, debug_mode):
    if isinstance(exception, RedirectException):
      self.redirect(exception.location)
    else:
      self.error(exception.status_code)
like image 56
Nick Johnson Avatar answered Jan 25 '23 20:01

Nick Johnson