美化JSON响应

要使JSON响应更具人类可读性,可能需要美化输出。默认情况下,Falcon的 JSONHandler 配置为最大限度地减少序列化开销。但是,您只需提供所需的 dumps 参数:

import functools
import json

from falcon import media

json_handler = media.JSONHandler(
    dumps=functools.partial(json.dumps, indent=4, sort_keys=True),
)

现在可以替换默认值 application/json response media handlers 用这个定制的 json_handler 使应用程序的JSON响应更漂亮(另请参见: 替换默认处理程序

备注

另一种调试方法是在客户端美化JSON,例如,流行的 HTTPie 默认情况下是这样做的。另一种选择是简单地通过管道将JSON响应传输到 jq

如果调试案例允许,则应首选客户端方法,因为它既不会增加服务器端的性能开销,也不需要任何定制工作。

支持可选缩进

互联网媒体类型(内容类型)协商是表达资源表示偏好的规范方式。虽然不是 application/json 媒体类型标准、一些框架(如Django睡觉框架)和服务支持使用 indent 内容类型参数。本食谱将这样的参数是否添加了“新功能”的解释留给了读者 RFC 6836, Section 4.3

假设我们想要添加JSON indent 对Falcon应用程序的支持,这可以通过 custom media handler

import cgi
import json

import falcon


class CustomJSONHandler(falcon.media.BaseHandler):
    MAX_INDENT_LEVEL = 8

    def deserialize(self, stream, content_type, content_length):
        data = stream.read()
        return json.loads(data.decode())

    def serialize(self, media, content_type):
        _, params = cgi.parse_header(content_type)
        indent = params.get('indent')
        if indent is not None:
            try:
                indent = int(indent)
                # NOTE: Impose a reasonable indentation level limit.
                if indent < 0 or indent > self.MAX_INDENT_LEVEL:
                    indent = None
            except ValueError:
                # TODO: Handle invalid params?
                indent = None

        result = json.dumps(media, indent=indent, sort_keys=bool(indent))
        return result.encode()

此外,我们还需要实现内容类型协商来接受缩进的JSON内容类型以进行响应序列化。最低限度的示例使用如下所述的中间件组件: 内容类型协商

为安装此处理程序后 application/json 响应媒体,以及添加协商中间件,我们应该能够产生缩进的JSON输出(构建在首页之上 QuoteResource 示例):

$ curl -H 'Accept: application/json; indent=4' http://localhost:8000/quote
{
    "author": "Grace Hopper",
    "quote": "I've always been more interested in the future than in the past."
}

警告

在公共API中实现这一点可能被视为一种不必要的攻击手段。

在发生拒绝服务攻击的情况下,您将为攻击者提供一种增加CPU负载的便捷方法,只需请求缩进输出即可,尤其是在有大型JSON响应可用的情况下。

此外,使用缩进和不使用缩进重播完全相同的请求可能会揭示对计时攻击有用的信息,特别是如果攻击者能够猜测所使用的JSON模块的确切风格。