媒体

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)
关键字参数
  • 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媒体类型处理程序的抽象基类。

deserialize(stream, content_type, content_length) object

反序列化 falcon.Request 身体。

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

注解

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

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

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

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

返回

反序列化对象。

返回类型

object

deserialize_async(stream, content_type, content_length) object

反序列化 falcon.Request 身体。

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

注解

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

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

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

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

返回

反序列化对象。

返回类型

object

serialize(media, content_type) bytes

上序列化媒体对象 falcon.Response

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

注解

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

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

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

返回

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

返回类型

bytes

serialize_async(media, content_type) bytes

上序列化媒体对象 falcon.Response

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

注解

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

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

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

返回

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

返回类型

bytes

小技巧

为了在 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