web-dev-qa-db-fra.com

Comment renvoyer un code d'erreur HTTP sans modèle par défaut dans Tornado?

J'utilise actuellement les éléments suivants pour générer une requête HTTP incorrecte:

raise tornado.web.HTTPError(400)

qui retourne une sortie HTML:

<html><title>400: Bad Request</title><body>400: Bad Request</body></html>

Est-il possible de ne renvoyer que le code de réponse HTTP avec un corps personnalisé?

30
S-K'

Vous pouvez simuler RequestHandler.send_error method:

class MyHandler(tornado.web.RequestHandler):
    def get(self):
        self.clear()
        self.set_status(400)
        self.finish("<html><body>My custom body</body></html>")
37
VisioN

Tornado appelle RequestHandler.write_error pour générer des erreurs. Une alternative à l’approche de VisioN serait donc la remplacer, comme suggéré par Tornado docs . L’avantage de cette approche est qu’elle vous permettra d’augmenter HTTPError comme auparavant.

La source de RequestHandler.write_error est ici . Vous trouverez ci-dessous un exemple de modification simple de write_error qui modifiera le code de statut et modifiera la sortie si vous fournissez une raison dans kwargs. 

def write_error(self, status_code, **kwargs):
    if self.settings.get("serve_traceback") and "exc_info" in kwargs:
        # in debug mode, try to send a traceback
        self.set_header('Content-Type', 'text/plain')
        for line in traceback.format_exception(*kwargs["exc_info"]):
            self.write(line)
        self.finish()
    else:
        self.set_status(status_code)
        if kwargs['reason']:
            self.finish(kwargs['reason'])
        else: 
            self.finish("<html><title>%(code)d: %(message)s</title>"
                "<body>%(code)d: %(message)s</body></html>" % {
                    "code": status_code,
                    "message": self._reason,
                })
23
Rod Hyde

Il est préférable d'utiliser l'interface standard et de définir votre message personnalisé sur la variable HTTPError.

raise tornado.web.HTTPError(status_code=code, log_message=custom_msg)

Vous pouvez ensuite analyser l'erreur dans votre RequestHandler et rechercher le message suivant:

class CustomHandler(tornado.web.RequestHandler):
    def write_error(self, status_code, **kwargs):
        err_cls, err, traceback = kwargs['exc_info']
        if err.log_message and err.log_message.startswith(custom_msg):
            self.write("<html><body><h1>Here be dragons</h1></body></html>")
6
punkrockpolly
def write_error(self, status_code, **kwargs):
    #Function to display custom error page defined in the handler.
    #Over written from base handler.
    data = {}
    data['code'] = status_code
    data['message'] = httplib.responses[status_code]
    # your other conditions here to create data dict
    self.write(TEMPLATES.load('error.html').generate(data=data))

quand jamais self.send_error () call est initié write_error () function est appelé par le gestionnaire de requêtes. Ainsi, vous pouvez créer votre dictée de données d'erreur personnalisée ici et la restituer à votre page d'erreur personnalisée.

http.responses [code_état] renvoie le texte du code d'erreur du type "page introuvable" en fonction du code d'état.

5
Somesh

Vous pouvez aussi remplacer get_error_html method dans votre gestionnaire .

import tornado.web
class CustomHandler(tornado.web.RequestHandler):
    def get_error_html(self, status_code, **kwargs);
        self.write("<html><body><h1>404!</h1></body></html>")
...
def get(self):
...
4
TIO

Cet échange clarifie certaines des approches suggérées ici et actualise le mot clé reason (que je pensais essayer).

Q: (par mrtn)

"Je souhaite utiliser raise tornado.web.HTTPError(400, reason='invalid request') pour transmettre un motif personnalisé à la réponse d'erreur et j'espère pouvoir le faire en redéfinissant la méthode write_error (self, status_code, **kwargs)

"Mais il semble que je ne peux accéder qu'à self._reason à l'intérieur de write_error, ce qui n'est pas ce que je veux. J'ai aussi essayé kwargs['reason'] mais cela n'existe pas."

A: (par le développeur principal de Tornado @bendarnell)

"L'exception qui a exposé l'erreur est disponible pour write_error sous la forme d'un triple exc_info dans les arguments de mots clés. Vous pouvez accéder au champ de motif avec quelque chose comme:

if "exc_info" in kwargs:
    e = kwargs["exc_info"][1]
    if isinstance(e, tornado.web.HTTPError):
        reason = e.reason

"Mais notez que le champ reason est essentiellement obsolète (il n’est pas présent dans HTTP/2), ce n’est donc probablement pas la meilleure façon de faire ce que vous essayez de faire ici (le champ HTTPError de log_message est un peu mieux, mais toujours pas Créez simplement votre propre exception au lieu d’utiliser HTTPError; votre substitution write_error peut utiliser self.set_status(400) lorsqu’elle détecte le type d’exception approprié. "

1
scharfmn