How do I return HTTP error code without default template in Tornado?

后端 未结 7 2144
情深已故
情深已故 2021-02-01 02:40

I am currently using the following to raise a HTTP bad request:

raise tornado.web.HTTPError(400)

which returns a html output:

&         


        
相关标签:
7条回答
  • 2021-02-01 03:10

    This exchange clarifies some of the approaches suggested here, and discounts the reason keyword (which I was thinking about trying).

    Q: (by mrtn)

    "I want to use raise tornado.web.HTTPError(400, reason='invalid request') to pass a custom reason to the error response, and I hope to do this by overriding the write_error (self, status_code, **kwargs) method.

    "But it seems that I can only access self._reason inside write_error, which is not what I want. I also tried kwargs['reason'] but that does not exist."

    A: (by Tornado lead developer @bendarnell)

    "The exception that exposed the error is available to write_error as an exc_info triple in the keyword arguments. You can access the reason field with something like this:

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

    "But note that the reason field is essentially deprecated (it is not present in HTTP/2), so it's probably not the best way to do whatever you're trying to do here (HTTPError's log_message field is a little better, but still not ideal). Just raise your own exception instead of using HTTPError; your write_error override can use self.set_status(400) when it sees the right kind of exception."

    0 讨论(0)
  • 2021-02-01 03:19
    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))
    

    when ever self.send_error() call is initiated write_error() function is called by the request handler. So you can create your custom error data dict here and render it to your custom error page.

    http.responses[status_code] returns the error code text like "page not found" based on the status code.

    0 讨论(0)
  • 2021-02-01 03:20

    It's better to use the standard interface and define your custom message on the HTTPError.

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

    You can then parse the error in your RequestHandler and check for the message:

    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>")
    
    0 讨论(0)
  • 2021-02-01 03:24

    Also you can override get_error_html method in your handler. For example:

    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):
    ...
    
    0 讨论(0)
  • 2021-02-01 03:25

    For json error response i use follow template:

    Request handler:

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

    Errors handler:

    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)
    
    0 讨论(0)
  • 2021-02-01 03:32

    You may simulate 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>")
    
    0 讨论(0)
提交回复
热议问题