RFC-7807 implementation for Tornado

build coverage docs download license source

This library provides a version of tornado.web.RequestHandler.send_error that speaks application/problem+json instead of HTML. The easiest way to use this library is to inherit from problemdetails.ErrorWriter and call send_error() with additional parameters.

from tornado import web
import problemdetails


class MyHandler(problemdetails.ErrorWriter, web.RequestHandler):
   def get(self):
      try:
         self.do_something_hard()
      except SomeException as error:
         self.send_error(500, title="Failed to do_something_hard")
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json

{
   "title": "Failed to do_something_hard",
   "type": "https://tools.ietf.org/html/rfc7231#section-6.6.1"
}

As an alternative, you can raise a problemdetails.Problem instance and let the Tornado exception handling take care of eventually calling write_error. The following snippet produces the same output as the previous example.

from tornado import web
import problemdetails


class MyHandler(problemdetails.ErrorWriter, web.RequestHandler):
   def get(self):
      if not self.do_something_hard():
         raise problemdetails.Problem(status_code=500,
                                      title='Failed to do_something_hard')

The problemdetails.Problem instance passes all of the keyword parameters through in the resulting message so it is very easy to add fields. The interface of tornado.web.RequestHandler.send_error is less expressive since keyword parameters may be swallowed by intervening code.

Reference

class problemdetails.ErrorWriter(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs)[source]

Render application/problem+json in write_error

Include this class in the base class list to return errors as application/problem+json documents instead of HTML.

write_error(status_code, **kwargs)[source]

Render application/problem+json documents instead of HTML.

Parameters
  • status_code (int) – HTTP status code that we returned

  • detail (str) – optional detail field to include in the error document. This field is omitted by default.

  • instance (str) – optional instance to include in the error document. This field is omitted by default.

  • title (str) – optional title to include in the error document. THis field is omitted by default.

  • type (str) – optional type field to include in the error document. This field defaults to a link to the official HTTP specification of status_code if omitted and status_code is a standard code.

See RFC 7807#section-3.1 for a description of each optional field.

class problemdetails.Problem(status_code, *args, **kwargs)[source]

An exception that will be translated into a json document.

Parameters
  • status_code (int) – HTTP status code to return

  • kwargs – additional keyword parameters are included in the response document

problemdetails.ErrorWriter.write_error() recognizes this exception type and renders document as the problem+json result. The status property is set to status_code and the type property will be set by write_error unless it is explicitly set.

document

The keyword parameters are collected into this dict and rendered as the response document

Mapping of HTTP status code to type link.

This table maps HTTP status codes to the IANA registered specification for the code. You can add additional links or replace ones that are here as you see fit. The error writer uses this table to generate the default type link in responses.

Release History

0.0.4 (2 Apr 2019)

  • Made compatible with Python 2.7, Tornado 4.4, Tornado 4.5, & Tornado 5.

0.0.2 (1 Apr 2019)

0.0.1 (31 Mar 2019)

  • Initial alpha release containing a very simple implementation.