阅读(608) (0)

Tornado RequestHandler和Application类

2022-03-08 10:39:11 更新

Tornado提供了一个具有异步功能的简单 Web 框架,允许它扩展到大量打开的连接,使其成为长轮询的理想选择。

这是一个简单的“Hello, world”示例应用程序:

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

if __name__ == "__main__":
    application = tornado.web.Application([
        (r"/", MainHandler),
    ])
    application.listen(8888)
    tornado.ioloop.IOLoop.current().start()

线路安全说明

一般来说,​RequestHandler和 Tornado 中其他地方的方法不是线程安全的。 特别是 ​write()​、​finish()​ 和 ​flush()​ 等方法只能从主线程调用。 如果您使用多个线程,重要的是在完成请求之前使用 ​IOLoop.add_callback​ 将控制权转移回主线程,或者将其他线程的使用限制为 ​IOLoop.run_in_executor​ 并确保您在执行程序中运行的回调不引用 到 Tornado 对象。

请求处理程序

HTTP 请求处理程序的基类。

子类必须至少定义下面“入口点”部分中定义的方法之一。

应用程序不应直接构造 ​RequestHandler ​对象,子类不应覆盖 ​__init__​ (而是覆盖初始化)。

入口点

RequestHandler.initialize() → None

子类初始化的钩子,为每个请求调用。

作为 URLSpec 的第三个参数传递的字典将作为关键字参数提供给 initialize()。

示例如下:

class ProfileHandler(RequestHandler):
    def initialize(self, database):
        self.database = database

    def get(self, username):
        ...

app = Application([
    (r'/user/(.*)', ProfileHandler, dict(database=database)),
    ])

RequestHandler.prepare() → 可选项[Awaitable[None]]

在 ​get​/​post​等之前的请求开始时调用。

覆盖此方法以执行通用初始化,而不管请求方法如何。

异步支持:使用 ​async def​ 或用 ​gen.coroutine​ 装饰此方法以使其异步。 如果此方法返回 ​Awaitable​,则在 ​Awaitable​ 完成之前不会继续执行。

3.1 版新功能:异步支持。

RequestHandler.on_finish() → None

在请求结束后调用。

重写此方法以执行清理、记录等。此方法是准备的对应方法。 ​on_finish​ 可能不会产生任何输出,因为它是在响应发送到客户端之后调用的。

实现以下任一方法(统称为 HTTP 动词方法)来处理相应的 HTTP 方法。 可以使用 ​async def​ 关键字或 ​gen.coroutine​ 使这些方法异步。

这些方法的参数来自 ​URLSpec​:正则表达式中的任何捕获组都将成为 HTTP 动词方法的参数(如果组被命名,则为关键字参数,如果未命名,则为位置参数)。

要支持不在此列表中的方法,请覆盖类变量 SUPPORTED_METHODS:

class WebDAVHandler(RequestHandler):
    SUPPORTED_METHODS = RequestHandler.SUPPORTED_METHODS + ('PROPFIND',)

    def propfind(self):
        pass

输入

argument​方法提供对 HTML 表单样式参数的支持。 这些方法可用于单数和复数形式,因为 HTML 表单是模棱两可的,并且不区分单数参数和包含一个条目的列表。 如果您希望使用其他格式的参数(例如 JSON),请自己解析 ​self.request.body​:

def prepare(self):
    if self.request.headers['Content-Type'] == 'application/x-json':
        self.args = json_decode(self.request.body)
    # Access self.args directly instead of using self.get_argument.

RequestHandler.get_argument(name: str, default: Union[None, str, RAISE] = RAISE, strip: bool = True) → Optional返回具有给定名称的请求 cookie 的值。

如果指定的 cookie 不存在,则返回默认值。

此方法仅返回请求中存在的 cookie。 它看不到由 set_cookie 在此处理程序中设置的传出 cookie。[str]

返回具有给定名称的参数的值。

如果未提供默认值,则认为该参数是必需的,如果缺少,将引发 ​MissingArgumentError​。

如果参数多次出现在请求中,我们返回最后一个值。

此方法搜索查询和正文参数。

RequestHandler.get_arguments(name: str, strip: bool = True) → List[str]

返回具有给定名称的参数列表。

如果参数不存在,则返回一个空列表。

此方法搜索查询和正文参数。

RequestHandler.get_query_argument(name: str, default: Union[None, str, RAISE] = RAISE, strip: bool = True) → Optional[str]

从请求查询字符串中返回具有给定名称的参数的值。

如果未提供默认值,则认为该参数是必需的,如果缺少,我们将引发 ​MissingArgumentError​。

如果参数多次出现在 url 中,我们返回最后一个值。

3.2 版中的新功能。

RequestHandler.get_query_arguments(name: str, strip: bool = True) → List[str]

返回具有给定名称的查询参数列表。

如果参数不存在,则返回一个空列表。

3.2 版中的新功能。

RequestHandler.get_body_argument(name: str, default: Union[None, str, RAISE] = RAISE, strip: bool = True) → Optional[str]

从请求正文返回具有给定名称的参数的值。

如果未提供默认值,则认为该参数是必需的,如果缺少,我们将引发 ​MissingArgumentError​。

如果参数多次出现在 url 中,我们返回最后一个值。

3.2 版中的新功能。

RequestHandler.get_body_arguments(name: str, strip: bool = True) → List[str]

返回具有给定名称的主体参数列表。

如果参数不存在,则返回一个空列表。

3.2 版中的新功能。

RequestHandler.decode_argument(value: bytes, name: Optional[str] = None) → str

从请求中解码参数。

该参数已被百分比解码,现在是一个字节字符串。 默认情况下,此方法将参数解码为 utf-8 并返回一个 unicode 字符串,但这可能在子类中被覆盖。

此方法用作 ​get_argument()​ 和从 url 中提取并传递给 ​get()​/​post()​等值的过滤器。

如果已知,则提供参数的名称,但可以为 None(例如,对于 url 正则表达式中的未命名组)。

RequestHandler.request

tornado.httputil.HTTPServerRequest​ 对象包含其他请求参数,例如 标题和正文数据。

RequestHandler.path_kwargs

path_args​ 和 ​path_kwargs​ 属性包含传递给 HTTP 方法的位置和关键字参数。 这些属性是在调用这些方法之前设置的,因此这些值在准备期间可用。

输出

RequestHandler.set_status(status_code: int, reason: Optional[str] = None) → None

为我们的响应设置状态码。

参数:

  • status_code (int)​ -- 响应状态代码。
  • reason (str)​ -- 描述状态代码。 如果没有,它将从 http.client.responses 或“空”填写。

在 5.0 版更改: 不再验证响应代码是否在 ​http.client.responses​ 中。

RequestHandler.set_header(name: str, value: Union[bytes, str, int, numbers.Integral, datetime.datetime]) → None

设置给定的响应头名称和值。

所有标头值都转换为字符串(​datetime ​对象根据 ​Date ​表头的 HTTP 规范进行格式化)。

RequestHandler.add_header(name: str, value: Union[bytes, str, int, numbers.Integral, datetime.datetime]) → None

添加给定的响应表头和值。

与 ​set_header​ 不同,​add_header​ 可以被多次调用以返回同一个表头的多个值。

RequestHandler.clear_header(name: str) → None

清除传出标头,撤消先前的set_header调用。

请注意,此方法不适用于 ​add_header​ 设置的多值表头。

RequestHandler.set_default_headers() → None

覆盖它以在请求开始时设置 HTTP 表头。

例如,这是设置自定义服务器表头的地方。 请注意,在请求处理的正常流程中设置此类表头可能无法满足您的要求,因为在错误处理期间可能会重置表头。

RequestHandler.write(chunk: Union[str, bytes, dict]) → None

将给定的块写入输出缓冲区。

要将输出写入网络,请使用下面的 ​flush()​ 方法。

如果给定的块是一个字典,我们将它写为 JSON 并将响应的 ​Content-Type​ 设置为 ​application/json​。 (如果您想将 JSON 作为不同的 ​Content-Type​ 发送,请在调用 ​write()​ 后调用 ​set_header​)。

请注意,由于潜在的跨站点安全漏洞,列表不会转换为 JSON。 所有 JSON 输出都应包含在字典中。

RequestHandler.flush(include_footers: bool = False) → Future[None]

将当前输出缓冲区刷新到网络。

在 4.0 版更改: 如果没有给出回调,现在返回 ​Future​。

在 6.0 版更改: 回调参数已删除。

RequestHandler.finish(chunk: Union[str, bytes, dict, None] = None) → Future[None]

完成此响应,结束 HTTP 请求。

将一个块传递给 ​finish()​ 等效于将该块传递给 ​write()​ 然后调用没有参数的 ​finish()​。

返回一个 ​Future ​,它可以选择等待以跟踪向客户端发送的响应。 当所有响应数据都已发送时,此 ​Future ​将解析,如果在发送所有数据之前关闭连接,则会引发错误。

在 5.1 版更改: 现在返回 ​Future ​而不是 ​None​。

RequestHandler.render(template_name: str, **kwargs) → Future[None]

使用给定参数呈现模板作为响应。

render()​ 调用了 ​finish()​,因此在它之后不能调用其他输出方法。

返回一个与​finish​返回的具有相同语义的​Future​。 等待这个 Future​是可选的。

在 5.1 版更改: 现在返回 ​Future​而不是 ​None​。

RequestHandler.render_string(template_name: str, **kwargs) → bytes

使用给定的参数生成给定的模板。

我们返回生成的字节串(utf8 格式)。 要使生成和编写模板作为响应,请使用上面的 ​render()​。

RequestHandler.get_template_namespace() → Dict[str, Any]

返回要用作默认模板命名空间的字典。

可以被子类覆盖以添加或修改值。

此方法的结果将与 ​tornado.template​ 模块中的其他默认值和渲染或渲染字符串的关键字参数相结合。

RequestHandler.redirect(url: str, permanent: bool = False, status: Optional[int] = None) → None

将重定向发送到给定的(可选相对)URL。

如果指定了 ​status ​参数,则该值用作 HTTP 状态代码; 否则根据永久参数选择 301(永久)或 302(临时)。 默认值为 302(临时)。

RequestHandler.send_error(status_code: int = 500, **kwargs) → None

将给定的 HTTP 错误代码发送到浏览器。

如果已经调用了 ​flush()​,则不可能发送错误,因此此方法将简单地终止响应。 如果输出已写入但尚未刷新,它将被丢弃并替换为错误页面。

覆盖 ​write_error()​ 以自定义返回的错误页面。 额外的关键字参数被传递给 ​write_error​。

RequestHandler.write_error(status_code: int, **kwargs) → None

覆盖以实现自定义错误页面。

write_error ​可以像往常一样调用 ​write​、​render​、​set_header ​等来产生输出。

如果此错误是由未捕获的异常(包括 HTTPError)引起的,则 ​exc_info ​三元组将以 ​kwargs["exc_info"]​ 的形式提供。 请注意,对于 ​sys.exc_info()​ 或 ​traceback.format_exc​ 等方法而言,此异常可能不是“当前”异常。

RequestHandler.clear() → None

重置此响应的所有表头和内容。

RequestHandler.render_linked_js(js_files: Iterable[str]) → str

用于呈现已呈现网页的最终 js 链接的默认方法。

在子类控制器中覆盖此方法以更改输出。

RequestHandler.render_embed_js(js_embed: Iterable[bytes]) → bytes

用于渲染网页的最终嵌入 js 的默认方法。

在子类控制器中覆盖此方法以更改输出。

RequestHandler.render_linked_css(css_files: Iterable[str]) → str

用于呈现已呈现网页的最终 css 链接的默认方法。

在子类控制器中覆盖此方法以更改输出。

RequestHandler.render_embed_css(css_embed: Iterable[bytes]) → bytes

用于为渲染网页渲染最终嵌入 css 的默认方法。

在子类控制器中覆盖此方法以更改输出。

Cookies

RequestHandler.get_cookie(name: str, default: Optional[str] = None) → Optional[str]

返回具有给定名称的请求 cookie 的值。

如果指定的 cookie 不存在,则返回默认值。

此方法仅返回请求中存在的 cookie。 它看不到由 ​set_cookie​ 在此处理程序中设置的传出 cookie。

RequestHandler.set_cookie(name: str, value: Union[str, bytes], domain: Optional[str] = None, expires: Union[float, Tuple, datetime.datetime, None] = None, path: str = '/', expires_days: Optional[float] = None, **kwargs) → None

使用给定选项设置传出 cookie 名称/值。

新设置的 cookie 不会通过 ​get_cookie​ 立即可见; 他们直到下一个请求才会出现。

expires 可以是 ​time.time​ 返回的数字时间戳、​time.gmtime​ 返回的时间元组或 ​datetime.datetime​ 对象。

额外的关键字参数直接在 cookies.Morsel 上设置。

RequestHandler.clear_cookie(name: str, path: str = '/', domain: Optional[str] = None) → None

删除具有给定名称的 cookie。

由于 cookie 协议的限制,您必须传递与设置 cookie 时使用的相同路径和域来清除 cookie(但无法在服务器端找出给定 cookie 使用了哪些值) .

和 ​set_cookie​ 类似,这个方法的效果要等到后面的请求才会看到。

RequestHandler.clear_all_cookies(path: str = '/', domain: Optional[str] = None) → None

删除用户随此请求发送的所有 cookie。

和 ​set_cookie ​类似,这个方法的效果要等到后面的请求才会看到。

在 3.2 版更改: 添加了路径和域参数。

RequestHandler.get_secure_cookie(name: str, value: Optional[str] = None, max_age_days: float = 31, min_version: Optional[int] = None) → Optional[bytes]

如果验证通过,则返回给定的签名 cookie,或者无。

解码后的 cookie 值作为字节字符串返回(与 ​get_cookie ​不同)。

与 ​get_cookie ​类似,此方法仅返回请求中存在的 cookie。 它在此处理程序中看不到由 ​set_secure_cookie ​设置的传出 cookie。

在 3.2.1 版更改:添加了 ​min_version​ 参数。 引入 cookie 版本 2; 默认情况下接受版本 1 和 2。

RequestHandler.get_secure_cookie_key_version(name: str, value: Optional[str] = None) → Optional[int]

返回安全 cookie 的签名密钥版本。

版本以 int 形式返回。

RequestHandler.set_secure_cookie(name: str, value: Union[str, bytes], expires_days: Optional[float] = 30, version: Optional[int] = None, **kwargs) → None

对 cookie 进行签名和时间戳记,使其无法被伪造。

您必须在应用程序中指定 ​cookie_secret ​设置才能使用此方法。 它应该是一个长的、随机的字节序列,用作签名的 HMAC 机密。

要使用此方法读取 cookie 集,请使用 ​get_secure_cookie()​。

请注意 ​expires_days ​参数设置浏览器中 cookie 的生命周期,但与 ​get_secure_cookie​ 的 ​max_age_days​ 参数无关。 None 值将生命周期限制为当前浏览器会话。

安全 cookie 可能包含任意字节值,而不仅仅是 unicode 字符串(与常规 cookie 不同)

和 ​set_cookie类似,这个方法的效果要等到后面的请求才会看到。

在 3.2.1 版更改:添加了​version​参数。 引入 cookie 版本 2 并将其设为默认值。

RequestHandler.create_signed_value(name: str, value: Union[str, bytes], version: Optional[int] = None) → bytes

对字符串进行签名和时间戳记,使其不能被伪造。

通常通过 ​set_secure_cookie ​使用,但作为非 cookie 使用的单独方法提供。 要解码未存储为 cookie 的值,请使用 ​get_secure_cookie ​的可选值参数。

在 3.2.1 版更改:添加了​version​参数。 引入 cookie 版本 2 并将其设为默认值。

应用程序配置

构成 Web 应用程序的请求处理程序的集合。

此类的实例是可调用的,并且可以直接传递给 HTTPServer 以服务于应用程序:

application = web.Application([
    (r"/", MainPageHandler),
])
http_server = httpserver.HTTPServer(application)
http_server.listen(8080)
ioloop.IOLoop.current().start()

此类的构造函数接收一个 ​Rule对象列表或对应于 ​Rule构造函数参数的值元组:​(matcher, target, [target_kwargs], [name])​,方括号中的值是可选的。 默认匹配器是 ​PathMatches​,因此也可以使用 ​(regexp, target)​ 元组来代替 ​(PathMatches(regexp), target)​。

常见的路由目标是 ​RequestHandler子类,但您也可以使用规则列表作为目标,从而创建嵌套路由配置:

application = web.Application([
    (HostMatches("example.com"), [
        (r"/", MainPageHandler),
        (r"/feed", FeedHandler),
    ]),
])

除此之外,您还可以使用嵌套的 ​Router实例、​HTTPMessageDelegate ​子类和可调用对象作为路由目标。

当我们收到请求时,我们按顺序遍历列表并实例化第一个请求类的实例,其正则表达式与请求路径匹配。 请求类可以指定为类对象或(完全限定的)名称。

字典可以作为元组的第三个元素 (​target_kwargs​) 传递,它将用作处理程序的构造函数和​initialize​方法的关键字参数。 此模式用于本示例中的 ​StaticFileHandler​(请注意,可以使用下面描述的 ​static_path ​设置自动安装 ​StaticFileHandler​):

application = web.Application([
    (r"/static/(.*)", web.StaticFileHandler, {"path": "/var/www"}),
])

我们使用 ​add_handlers方法支持虚拟主机(virtual hosts),该方法将主机的正则表达式作为第一个参数:

application.add_handlers(r"www\.myhost\.com", [
    (r"/article/([0-9]+)", ArticleHandler),
])

如果当前请求的主机不匹配,则 ​default_host参数值与主机的正则表达式匹配。

注意:不使用 TLS 的应用程序可能容易受到 DNS 重新绑定攻击。 此攻击与仅侦听 ​127.0.0.1或其他专用网络的应用程序特别相关。 必须使用适当的主机模式(而不是默认的​ r'.*'​)来防止这种风险。 ​default_host ​参数不得用于可能易受 DNS 重新绑定攻击的应用程序中。

您可以通过将 ​static_path ​设置作为关键字参数发送来提供静态文件。 我们将从 ​/static/ URI​ 提供这些文件(这可以通过 ​static_url_prefix设置进行配置),我们将从同一目录提供 ​/favicon.ico​ 和 ​/robots.txt​。 可以使用 ​static_handler_class设置指定 ​StaticFileHandler的自定义子类。

在 4.5 版更改: 与新的 ​tornado.routing​ 模块集成。

Application.listen(port: int, address: str = '', **kwargs) → tornado.httpserver.HTTPServer

在给定端口上为此应用程序启动 HTTP 服务器。

这是一个方便的别名,用于创建HTTPServer​对象并调用其监听方法。 ​HTTPServer.listen​ 不支持的关键字参数被传递给 ​HTTPServer构造函数。 对于高级用途(例如多进程模式),请勿使用此方法; 创建一个 ​HTTPServer并直接调用它的 ​TCPServer.bind/TCPServer.start​ 方法。

请注意,调用此方法后,您仍然需要调用 ​IOLoop.current().start()​ 来启动服务器。

返回 ​HTTPServer对象。

Application.add_handlers(handlers: List[Union[Rule, Tuple]])

将给定的处理程序附加到我们的处理程序列表中。

主机模式按照添加的顺序依次处理, 将考虑所有匹配模式。

Application.get_handler_delegate(request: tornado.httputil.HTTPServerRequest, target_class: Type[tornado.web.RequestHandler], target_kwargs: Optional[Dict[str, Any]] = None, path_args: Optional[List[bytes]] = None, path_kwargs: Optional[Dict[str, bytes]] = None) → tornado.web._HandlerDelegate

返回可以为应用程序和 ​RequestHandler子类提供请求的 ​HTTPMessageDelegate​。

参数:

  • request(httputil.HTTPServerRequest) – 当前的 HTTP 请求。
  • target_class(RequestHandler) – 一个 RequestHandler 类。
  • target_kwargs(dict) -- target_class 构造函数的关键字参数。
  • path_args(list) – target_class HTTP 方法的位置参数,将在处理请求(get、post 或任何其他)时执行。
  • path_kwargs(dict) -- target_class HTTP 方法的关键字参数。

Application.reverse_url(name: str, *args) → str

返回名为 name 的处理程序的 URL 路径

该处理程序必须作为命名的 ​URLSpec ​添加到应用程序中。

Args 将替换 ​URLSpec ​正则表达式中的捕获组。 如有必要,它们将被转换为字符串,编码为 utf8 并转义 url。

Application.log_request(handler: tornado.web.RequestHandler) → None

将完成的 HTTP 请求写入日志。

默认情况下写入 python 根记录器。 要更改此行为,请继承 Application 并覆盖此方法,或将应用程序设置字典中的函数作为 ​log_function传递。

class tornado.web.URLSpec(pattern: Union[str, Pattern[AnyStr]], handler: Any, kwargs: Optional[Dict[str, Any]] = None, name: Optional[str] = None)

指定 URL 和处理程序之间的映射。
参数:

  • pattern​:要匹配的正则表达式。 正则表达式中的任何捕获组都将作为参数传递给处理程序的 get/post等方法(如果命名则按关键字,如果未命名则按位置。命名和未命名的捕获组不能在同一规则中混合使用)。
  • handler​:要调用的 RequestHandler 子类。
  • kwargs​(可选):要传递给处理程序构造函数的附加参数字典。
  • name​(可选):此处理程序的名称, 由 ​reverse_url ​使用。

URLSpec类也可以在名称 ​tornado.web.url​下使用。