views:

46

answers:

1

The title is horrible, i know; I'm terrible at titles on SO here.

I'm wondering what would be the best way to present unified error responses in a webapi when errors could be raised deep inside the application.

The errors deep down in the app don't know anything about the web layer (nor should they), so how can the web layer classify myapp.PermissionError into a 403, json.DecodeError into a 400, myapp.driver.InvalidValue into 500, etc.

I have a few ideas, but I'm not a big fan of any of them.

(As the snippets might imply, this is a python app on linux)

  1. Use a lot of except blocks to match the exception type i want. This is what i'm currently doing but its growing unwieldy (i'm already up to 8, and there are plenty more to go).

    try
      business.DoIt()
    except DecodingError:
      respond(400)
    except PermissionError:
      response(403)
    ...etc...
    
  2. Creating a mapping or list of exception types and map them to response codes. This doesn't seem much better than (1) in the end, but it does clean up the code.

    error_map = [(DecodingError, 400), (PermissionError, 403)]
    try:
      DoIt()
    except Exception, exc:
      for type, code in error_map:
        if isinstance(exc, type):
           response(code)
           return
    
  3. Add an interface to every exception class that provides the response code, but I don't like this because then the exceptions are carrying web-layer specific information (even if they live deep down in a driver that doesn't care about the web layer at all). I do like how "automatic" the web error response is, though.

    class PermissionError(Exception):
      web_status_code = 403
    try:
      Doit()
    except:
      response(exc.web_status_code)
    
+1  A: 

I like option 1. It may be a little more verbose, but it's also very clear.

Option 2 separates the point at which the exception is thrown from where the decision about what to do with it is made. In reality, that likely wouldn't be too much of an issue, but why split it up if you don't have to?

I agree that option 3 is pretty ugly. No need to deal with the error behavior at that level, just throw the exception.

Josh Wright