美化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 默认情况下执行。

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

支持可选缩进

处理HTTP表示首选项的一种规范方法是媒体内容类型协商。虽然不是 application/json 媒体类型标准,一些框架(如Django REST框架)和服务支持使用 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输出(构建在frontpage上 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模块的确切风格时。