如何在Tornado中返回没有默认模板的HTTP错误代码?

时间:2012-12-05 19:30:04

标签: python tornado

我目前正在使用以下内容来引发HTTP错误请求:

raise tornado.web.HTTPError(400)

返回html输出:

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

是否可以仅使用自定义正文返回HTTP响应代码?

7 个答案:

答案 0 :(得分:37)

您可以模拟RequestHandler.send_error方法:

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

答案 1 :(得分:23)

Tornado要求RequestHandler.write_error输出错误,因此VisioN's approach的替代方法会根据Tornado docs的建议覆盖它。这种方法的优势在于它允许您像以前一样提升HTTPError

RequestHandler.write_error的来源是here。下面你可以看到一个简单修改write_error的例子,如果你在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,
                })

答案 2 :(得分:6)

最好使用标准界面并在HTTPError上定义自定义消息。

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

然后,您可以解析RequestHandler中的错误并检查消息:

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>")

答案 3 :(得分:5)

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))

启动 self.send_error()调用时,请求处理程序调用 write_error()函数。因此,您可以在此处创建自定义错误数据dict并将其呈现给自定义错误页面。

http.responses [status_code]根据状态代码返回错误代码文本,如“找不到页面”。

答案 4 :(得分:4)

您也可以在处理程序中覆盖 get_error_html 方法。 例如:

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):
...

答案 5 :(得分:1)

This exchange澄清了此处建议的一些方法,并对reason关键字(我正在考虑尝试)进行折扣。

问:(通过mrtn)

&#34;我想使用raise tornado.web.HTTPError(400, reason='invalid request')将自定义原因传递给错误响应,我希望通过覆盖write_error (self, status_code, **kwargs)方法来实现此目的。

&#34;但似乎我只能在self._reason内访问write_error,这不是我想要的。我也尝试了kwargs['reason'],但这不存在。&#34;

A:(由Tornado首席开发人员@bendarnell撰写)

&#34; write_error在关键字参数中以exc_info三元组的形式提供了公开错误的异常。您可以使用以下内容访问原因字段:

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

&#34;但请注意,reason字段基本上已弃用(HTTP / 2中不存在),因此它可能不是您做任何事情的最佳方式。试图在这里做(HTTPError&#39; log_message字段稍微好一点,但仍然不理想)。只需提出自己的例外,而不是使用HTTPError;当write_error覆盖看到正确的异常时,self.set_status(400)覆盖可以使用Sub dural() ActiveSheet.Copy Rows("33:1048576").Delete Columns("F:xfd").Delete End Sub 。&#34;

答案 6 :(得分:0)

对于json错误响应,我使用以下模板:

请求处理程序:

import json
from tornado.web import RequestHandler
from src.lib.errors import HTTPBadRequest


class JsonHandler(RequestHandler):

    def prepare(self):
        content_type = ''
        if "Content-Type" in self.request.headers:
            content_type = self.request.headers['Content-Type']

        if content_type == 'application/json':
            try:
                self.request.body = json.loads(self.request.body.decode('utf-8'))
            except ValueError:
                raise HTTPBadRequest

    def write_error(self, *args, **kwargs):
        err_cls, err, traceback = kwargs['exc_info']
        self.set_status(err.status_code)
        if err.description:
            self.write_json(err.description)
        self.finish()

    def set_default_headers(self):
        self.set_header('Content-Type', 'application/json')

    def write_json(self, response):
        self.write(json.dumps(response))

错误处理程序:

from typing import Any
from tornado import httputil


class BaseHTTPError(Exception):
    def __init__(
        self, status_code: int = 500, description=None, *args: Any, **kwargs: Any
    ) -> None:
        if description is None:
            description = {}
        self.status_code = status_code
        self.description = description
        self.args = args
        self.kwargs = kwargs

    def __str__(self) -> str:
        message = "HTTP %d: %s" % (
            self.status_code,
            httputil.responses.get(self.status_code, "Unknown"),
        )
        return message


class HTTPBadRequest(BaseHTTPError):
    def __init__(self, *args, **kwargs):
        super().__init__(status_code=400, description={"error": "Bad Request"}, *args, **kwargs)