KimiNewt
KimiNewt

Reputation: 529

Reraising an exception as an HTTP error in Pyramid

I have a web app in python Pyramid which calls various other code in python which may raise an exception. Instead of the user receiving a "500 Internal Error", I'd like them to get a more specific error, for instance if MyException is thrown, show a 503 Error. I tried to do this:

@view_config(context=MyException, permission='view')
def custom_exc(exc, request):
   raise HTTPServiceUnavailable(exc.message)

However, that fails because it is for some reason unauthorized:

HTTPForbidden: Unauthorized: custom_exc failed permission check

My ACL is as follows:

class RootFactory(object):
    __acl__ = [
        (Allow, 'admin', ('view',))
        ]

I am connected with the user admin and it works perfectly for other views.

Does anyone know how to solve this or else how to "chain" exceptions in Pyramid in a different way?

Upvotes: 2

Views: 663

Answers (1)

Sascha Gottfried
Sascha Gottfried

Reputation: 3329

Learn from a customized version of famous ToDoPyramid example application. This way I translate an internal technical event, a database exception, into a meaningful application specific message within custom exception view code. Some guys call this a layer of abstraction or information hiding.

Do not protect these exception views with permissions, since you should protect code that does stuff and CAN raise exceptions.

from sqlalchemy.exc import OperationalError as SqlAlchemyOperationalError

@view_config(context=SqlAlchemyOperationalError)
def failed_sqlalchemy(exception, request):
    """catch missing database, logout and redirect to homepage, add flash message with error
    implementation inspired by pylons group message
    https://groups.google.com/d/msg/pylons-discuss/BUtbPrXizP4/0JhqB2MuoL4J
    """

    msg = 'There was an error connecting to database'
    request.session.flash(msg, queue='error')
    headers = forget(request)
    # Send the user back home, everything else is protected
    return HTTPFound(request.route_url('home'), headers=headers)

Upvotes: 2

Related Questions