10
votes

Middleware de bouteille pour attraper des exceptions d'un certain type?

Compte tenu de ce code de bouteille simple:

@route('/foo')
def foo():
    return bar()


3 commentaires

Pourriez-vous simplement ne pas dériver votre exception de bouteille.httpresponse avec le type d'exception, puis la chose appropriée pour commencer ou la source de votre exception ne faisait pas partie de votre application Web et donc pas déjà dépendant de la bouteille?


L'exception est lancée d'une bibliothèque indépendante; La bouteille n'est qu'un devant.


Est-ce qu'un plugin de bouteille suffit?


3 Réponses :


4
votes

Bouteille respecte la spécification WSGI. Vous pouvez utiliser un middleware classique WSGI

from bottle import route, default_app, run, request

# push an application in the AppStack
default_app.push()


@route('/foo')
def foo():
    raise KeyError()


# error view
@route('/error')
def error():
    return 'Sorry an error occured %(myapp.error)r' % request.environ


# get the bottle application. can be a Bottle() instance too
app = default_app.pop()
app.catchall = False


def error_catcher(environ, start_response):
    # maybe better to fake the start_response callable but this work
    try:
        return app.wsgi(environ, start_response)
    except Exception as e:
        # redirect to the error view if an exception is raised
        environ['PATH_INFO'] = '/error'
        environ['myapp.error'] = e
        return app.wsgi(environ, start_response)


# serve the middleware instead of the applicatio
run(app=error_catcher)


3 commentaires

Merci, mais y a-t-il une façon de montrer la sortie d'erreur (en tant que JSON) et de définir le code d'état; Sans redirection? - Je pense peut-être une lambda dans le error_catcher bloc ...


C'est une redirection interne. Et la vue Erreur peut renvoyer un peu de JSON. ERROR_CATCHER est une application WSGI afin que vous puissiez faire ce que vous voulez / besoin. En savoir plus sur l'application WSGI: webpytHon.codepoint.net/wsgi_application_interface


Alors, comment puis-je le faire sans une fonction séparée? - E.g.: Une approche Lambda?



8
votes

Vous pouvez le faire élégamment avec un plugin levier Abort code> :

from bottle import abort

def error_translation(func):
    def wrapper(*args,**kwargs):
        try:
            func(*args,**kwargs)
        except ValueError as e:
            abort(400, e.message)
    return wrapper

app.install(error_translation)


3 commentaires

Quel est le avortement () ? - Cela signifie-t-il os.abort () ?


@Valk vient d'être édité pour ajouter plus de contexte - c'est une fonction fournie par bouteille pour avorter une demande avec un code + message


Merci pour la clarification.



1
votes

Vous pouvez l'utiliser à la place:

from bottle import error, run, route

@error(500)
def error_handler_500(error):
    return json.dumps({"status": "error", "message": str(error.exception)})

@route("/")
def index():
    a = {}
    a['aaa']

run()


0 commentaires