媒体

Falcon允许轻松和定制的互联网媒体类型处理。默认情况下,Falcon只为JSON和HTML(URL编码和多部分)表单启用处理程序。但是,可以通过 falcon.RequestOptionsfalcon.ResponseOptions 在您的 falcon.App .

备注

WebSocket媒体的处理方式与常规HTTP请求不同。有关WebSocket媒体处理程序的信息,请参阅: 媒体处理程序 在WebSocket部分。

使用

如果要创建JSON API,则需要零配置。简单使用 get_media()media (WSGI),或 get_media()media (ASGI)让Falcon帮你做重活。

import falcon


class EchoResource:
    def on_post(self, req, resp):
        # Deserialize the request body based on the Content-Type
        #   header in the request, or the default media type
        #   when the Content-Type header is generic ('*/*') or
        #   missing.
        obj = req.get_media()

        message = obj.get('message')

        # The framework will look for a media handler that matches
        #   the response's Content-Type header, or fall back to the
        #   default media type (typically JSON) when the app does
        #   not explicitly set the Content-Type header.
        resp.media = {'message': message}
        resp.status = falcon.HTTP_200

警告

一次 falcon.Request.get_media()falcon.asgi.Request.get_media() 在请求上调用时,它将使用请求的正文流。为避免不必要的开销,Falcon将仅在第一次引用请求介质时对其进行处理。后续交互将使用缓存的对象。

正在验证媒体

Falcon目前只提供一个JSON模式媒体验证程序;但是,JSON模式非常通用,可以用来验证JSON也支持的任何反序列化媒体类型(如dicts、list等)。

falcon.media.validators.jsonschema.validate(req_schema=None, resp_schema=None, is_async=False)[源代码]

验证 req.media 使用JSON架构。

这个装饰器通过 jsonschema PYPI提供的包。语义验证通过 格式 已为实现的默认检查程序启用关键字 jsonschema.FormatChecker .

如果请求媒体验证失败, MediaValidationError 是由装饰师养大的。默认情况下,此错误呈现为400 (HTTPBadRequest )的回应 titledescription 属性来解释验证失败,但可以通过添加自定义错误来修改此行为 handlerMediaValidationError

备注

这个 jsonschema 必须单独安装软件包才能使用此修饰符,因为Falcon默认情况下不安装它。

json-schema.org 有关定义兼容字典的详细信息。

关键字参数:
  • req_schema (dict) -- 遵循JSON模式规范的字典。将根据此架构验证请求。

  • resp_schema (dict) -- 遵循JSON模式规范的字典。将根据此架构验证响应。

  • is_async (bool) -- 设置为 True 让ASGI应用程序提供修饰的响应器是协程函数的提示(即,它是用 async def )或返回可等待的协程对象。通常,当使用 async def 产生的函数对象被标记,以指示它在被调用时返回协程,并且这可以被自动检测到。但是,可以使用常规函数返回一个可等待的协程对象,在这种情况下,需要一个提示来让框架知道预期会发生什么。此外,在使用Cython化的协程函数时,始终需要提示,因为Cython不会以可以预先检测到的方式标记它们,即使函数是使用 async def

示例

from falcon.media.validators import jsonschema

# -- snip --

@jsonschema.validate(my_post_schema)
def on_post(self, req, resp):

# -- snip --

如果JSON模式不满足您的需求,那么定制验证器的实现方式可能与上面的方法类似。

内容类型协商

Falcon目前只支持开箱即用的部分协商。默认情况下,当 get_media() 方法或 media 属性时,框架尝试基于 Content-Type 标题值。Falcon没有提供的缺失链接是 Accept 由用户提供的头和 Content-Type 在响应上设置标头。

如果您确实需要完整的协商,那么使用中间件很容易弥合这一差距。下面是一个如何做到这一点的示例:

class NegotiationMiddleware:
    def process_request(self, req, resp):
        resp.content_type = req.accept

异常处理

Falcon版本3更新了处理程序引发的异常的处理方式:

  • Falcon允许媒体处理程序尝试反序列化空体。对于不允许将空正文作为有效值的媒体类型,例如 JSON ,一个实例 falcon.MediaNotFoundError 应该提高。默认情况下,此错误将呈现为 400 Bad Request 对客户端的响应。通过将一个值传递给 default_when_empty 参数时调用 Request.get_media() 。在本例中,该值将由调用返回。

  • 如果处理程序在分析非空正文时遇到错误, falcon.MediaMalformedError 应该提高。原始异常(如果有)存储在 __cause__ 引发的实例的属性。默认情况下,此错误将呈现为 400 Bad Request 对客户端的响应。

如果处理程序在分析正文时引发任何异常,则 Request.get_media()Request.media 将导致同一异常的重新引发,除非该异常是 falcon.MediaNotFoundError 并将默认值传递给 default_when_empty 当前调用的属性。

外部处理程序应更新其逻辑以与内部Falcon处理程序对齐。

替换默认处理程序

默认情况下,框架安装 falcon.media.JSONHandlerfalcon.media.URLEncodedFormHandler ,以及 falcon.media.MultipartFormHandler 对于 application/jsonapplication/x-www-form-urlencoded ,以及 multipart/form-data 分别为媒体类型。

在创建App对象时,您可以添加或完全替换所有处理程序。例如,假设您想要编写一个发送和接收 MessagePack 。我们可以很容易地做到这一点,方法是告诉Falcon API我们需要默认的媒体类型 application/msgpack ,然后创建一个新的 Handlers 对象将该媒体类型映射到适当的处理程序。

下面的示例演示如何替换默认处理程序。因为Falcon提供了一个 MessagePackHandler 这在默认情况下是不启用的,我们在下面的示例中使用它。不过,您始终可以通过替身 custom media handler 根据需要。

import falcon
from falcon import media


handlers = media.Handlers({
    falcon.MEDIA_MSGPACK: media.MessagePackHandler(),
})

app = falcon.App(media_type=falcon.MEDIA_MSGPACK)

app.req_options.media_handlers = handlers
app.resp_options.media_handlers = handlers

或者,您也可以简单地更新现有的 Handlers 对象以保留默认处理程序:

import falcon
from falcon import media


extra_handlers = {
    falcon.MEDIA_MSGPACK: media.MessagePackHandler(),
}

app = falcon.App()

app.req_options.media_handlers.update(extra_handlers)
app.resp_options.media_handlers.update(extra_handlers)

这个 falcon 模块为常见媒体类型提供了许多常量。另请参阅: 媒体类型常量

备注

已配置的 falcon.Response JSON处理程序还用于序列化 falcon.HTTPError 以及 json 的属性 falcon.asgi.SSEvent 。中配置的JSON处理程序 falcon.Request 由以下用户使用 falcon.Request.get_param_as_json() 若要反序列化查询参数,请执行以下操作。

因此,在实现JSON媒体类型的自定义处理程序时,需要同步接口方法,这意味着 falcon.media.BaseHandler.serialize()falcon.media.BaseHandler.deserialize() ,即使在 ASGI 申请。默认的JSON处理程序, falcon.media.JSONHandler 已经实现了使用这两种类型的应用程序所需的方法。

支持的处理程序类型

class falcon.media.JSONHandler(dumps=None, loads=None)[源代码]

JSON媒体处理程序。

此处理程序使用Python的标准 json 库在默认情况下,但可以根据需要轻松配置为使用许多第三方JSON库中的任何一个。例如,通过使用替代库,您通常可以在cpython下实现显著的性能提升。在这方面的好选择包括 orjsonpython-rapidjsonmujson .

此处理程序将引发 falcon.MediaNotFoundError 当尝试分析空体时,或者 falcon.MediaMalformedError 如果在解析正文时发生错误。

备注

如果您要部署到Pypy,我们建议您坚持使用标准库的JSON实现,因为与第三方库相比,它在大多数情况下都会更快。

定制JSON库

您可以使用自定义JSON库替换默认的JSON处理程序(另请参阅: 替换默认处理程序 )。覆盖默认的JSON实现只需指定所需的 dumpsloads 功能::

import falcon
from falcon import media

import rapidjson

json_handler = media.JSONHandler(
    dumps=rapidjson.dumps,
    loads=rapidjson.loads,
)
extra_handlers = {
    'application/json': json_handler,
}

app = falcon.App()
app.req_options.media_handlers.update(extra_handlers)
app.resp_options.media_handlers.update(extra_handlers)

自定义序列化参数

即使您决定坚持使用stdlib json.dumpsjson.loads ,您可以使用以下命令包装它们 functools.partial 方法支持的自定义序列化或反序列化参数 dumpsloads 函数(另请参阅: 美化JSON响应 ):

import falcon
from falcon import media

from functools import partial

json_handler = media.JSONHandler(
    dumps=partial(
        json.dumps,
        default=str,
        sort_keys=True,
    ),
)
extra_handlers = {
    'application/json': json_handler,
}

app = falcon.App()
app.req_options.media_handlers.update(extra_handlers)
app.resp_options.media_handlers.update(extra_handlers)

默认情况下, ensure_ascii 传递给 json.dumps 功能。如果您重写 dumps 函数,则需要显式设置 ensure_asciiFalse 以便能够将Unicode字符序列化为UTF-8。这可以通过使用 functools.partial 要应用所需的关键字参数,请执行以下操作。也如上一段所示,您可以使用同样的技术来自定义 dumpsloads 功能::

from functools import partial

from falcon import media
import rapidjson

json_handler = media.JSONHandler(
    dumps=partial(
        rapidjson.dumps,
        ensure_ascii=False, sort_keys=True
    ),
)

定制JSON编码器

您也可以覆盖缺省值 JSONEncoder 通过使用自定义编码器并更新媒体处理程序 application/json 键入以使用该名称::

import json
from datetime import datetime
from functools import partial

import falcon
from falcon import media

class DatetimeEncoder(json.JSONEncoder):
    """Json Encoder that supports datetime objects."""

    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

app = falcon.App()

json_handler = media.JSONHandler(
    dumps=partial(json.dumps, cls=DatetimeEncoder),
)
extra_handlers = {
    'application/json': json_handler,
}

app.req_options.media_handlers.update(extra_handlers)
app.resp_options.media_handlers.update(extra_handlers)

备注

在测试使用定制JSON编码器的应用程序时,请记住 TestClient 是与应用程序分离的,它模拟请求,就好像它们是由第三方客户端(只是SANS网络)执行的一样。因此,传递 json 参数设置为 simulate_* 方法将有效地使用stdlib的 json.dumps() 。如果要序列化用于测试的自定义对象,则需要自己将它们转储到字符串中,并使用 body 参数来代替(随附 application/json 内容类型报头)。

关键字参数:
  • dumps (func) -- 在序列化JSON响应时使用的函数。

  • loads (func) -- 反序列化JSON请求时使用的函数。

class falcon.media.MessagePackHandler[源代码]

使用生成的处理程序 msgpack 模块。

此处理程序使用 msgpack.unpackb()msgpack.Packer().pack() 。MessagePack bin 类型用于区分Unicode字符串(类型为 str )和字节字符串(类型为 bytes )。

此处理程序将引发 falcon.MediaNotFoundError 当尝试分析空体时,它将引发 falcon.MediaMalformedError 如果在解析正文时发生错误。

备注

此处理程序需要额外的 msgpack 软件包(0.5.2或更高版本),必须安装在 falcon 来自Pypi:

$ pip install msgpack
class falcon.media.MultipartFormHandler(parse_options=None)[源代码]

多部分表单(内容类型 multipart/form-data )媒体处理程序。

这个 multipart/form-data HTML5表单的媒体类型在中定义 RFC 7578

多部分媒体类型本身在中定义 RFC 2046 section 5.1

备注

与其他框架中的许多表单解析实现不同,该处理程序不会立即使用流。相反,在迭代媒体对象时,按需使用流并将其解析为单独的正文部分。

有关解析申请表的示例,另请参阅: 多部分形式

parse_options

多部分表单分析器和实例的配置选项 BodyPart 它屈服了。

另请参阅: 解析器配置

类型:

MultipartParseOptions

class falcon.media.URLEncodedFormHandler(keep_blank=True, csv=False)[源代码]

URL编码的表单数据处理程序。

此处理程序分析 application/x-www-form-urlencoded 将HTML表单添加到 dict ,类似于URL查询参数的解析方式。空的正文将被解析为空的字典。

反序列化时,此处理程序将引发 falcon.MediaMalformedError 如果请求有效负载不能被解析为ASCII,或者如果有效负载中的任何URL编码字符串不是有效的UTF-8。

如文档所示, urllib.parse.urlencode ,序列化时,媒体对象必须是 dict 或由两个元素组成的序列 tuple 如果媒体对象中的任何值都是序列,则将每个序列元素转换为单独的参数。

关键字参数:
  • keep_blank (bool) -- 反序列化时是否保留窗体中的空字符串值。

  • csv (bool) -- 反序列化时是否将逗号分隔的表单值拆分为列表。

自定义处理程序类型

如果Falcon没有支持您的用例的Internet媒体类型处理程序,您可以使用Falcon提供的抽象基类轻松实现您自己的,如下所述。

总体而言 WSGI 应用程序仅使用同步方法,而 ASGI 应用程序只使用异步应用程序。被处理的JSON是一个例外,因为它也被框架的其他部分使用,而不仅仅是在媒体处理中。请参阅 note above 了解更多详细信息。

class falcon.media.BaseHandler[源代码]

Internet媒体类型处理程序的抽象基类。

serialize(media: object, content_type: str) bytes[源代码]

上序列化媒体对象 falcon.Response

默认情况下,此方法引发 NotImplementedError 。因此,必须覆盖它才能使用WSGI应用程序。如果子类仅与ASGI应用程序一起使用,则它们可以忽略此方法,只要它们重写 serialize_async()

备注

JSON媒体处理程序是一个例外,它要求也为ASGI应用程序实现同步版本。请参阅 this section 了解更多详细信息。

参数:
  • media (object) -- 可序列化对象。

  • content_type (str) -- 响应内容的类型。

返回:

从输入对象得到的序列化字节。

返回类型:

bytes

async serialize_async(media: object, content_type: str) bytes[源代码]

上序列化媒体对象 falcon.Response

此方法类似于 serialize() 只是它是异步的。默认实现只是调用 serialize() 。如果媒体对象可能是可等待的,或者应该异步读取,则子类必须覆盖默认实现才能处理这种情况。

备注

默认情况下, serialize() 方法引发 NotImplementedError 。因此,子类必须重写 serialize()serialize_async() 以便与ASGI应用程序兼容。

参数:
  • media (object) -- 可序列化对象。

  • content_type (str) -- 响应内容的类型。

返回:

从输入对象得到的序列化字节。

返回类型:

bytes

deserialize(stream: IO, content_type: str, content_length: Optional[int]) object[源代码]

反序列化 falcon.Request 身体。

默认情况下,此方法引发 NotImplementedError 。因此,必须覆盖它才能使用WSGI应用程序。如果子类仅与ASGI应用程序一起使用,则它们可以忽略此方法,只要它们重写 deserialize_async()

备注

JSON媒体处理程序是一个例外,它要求也为ASGI应用程序实现同步版本。请参阅 this section 了解更多详细信息。

参数:
  • stream (object) -- 要反序列化的可读类似文件的对象。

  • content_type (str) -- 请求内容的类型。

  • content_length (int) -- 请求内容的长度。

返回:

反序列化对象。

返回类型:

object

async deserialize_async(stream: IO, content_type: str, content_length: Optional[int]) object[源代码]

反序列化 falcon.Request 身体。

此方法类似于 deserialize() 只是它是异步的。缺省实现适应同步 deserialize() 方法通过 io.BytesIO 。为提高性能,媒体处理程序应重写此方法。

备注

默认情况下, deserialize() 方法引发 NotImplementedError 。因此,子类必须重写 deserialize()deserialize_async() 以便与ASGI应用程序兼容。

参数:
  • stream (object) -- 要反序列化的异步类文件对象。

  • content_type (str) -- 请求内容的类型。

  • content_length (int) -- 请求内容的长度,或 None 如果缺少Content-Long标头。

返回:

反序列化对象。

返回类型:

object

exhaust_stream = False

是否在完成反序列化后耗尽输入流。

对于不一定使用整个流,但反序列化的媒体对象是完整的并且不涉及进一步的流的处理程序来说,用尽流可能是有用的。

小技巧

为了在 Falcon app ,则必须将类的实例添加到应用程序的媒体处理程序(在中指定) RequestOptionsResponseOptions ,分别)。

参见: 替换默认处理程序 .

处理程序映射

class falcon.media.Handlers(initial=None)[源代码]

A dict -管理Internet媒体类型处理程序的类对象。

媒体类型常量

这个 falcon 模块为常见的媒体类型字符串提供了许多常量,包括:

falcon.MEDIA_JSON
falcon.MEDIA_MSGPACK
falcon.MEDIA_MULTIPART
falcon.MEDIA_URLENCODED
falcon.MEDIA_YAML
falcon.MEDIA_XML
falcon.MEDIA_HTML
falcon.MEDIA_JS
falcon.MEDIA_TEXT
falcon.MEDIA_JPEG
falcon.MEDIA_PNG
falcon.MEDIA_GIF