Tornado RequestHandler和Application類

2022-03-08 15:52 更新

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? 并確保您在執(zhí)行程序中運行的回調不引用 到 Tornado 對象。

請求處理程序

HTTP 請求處理程序的基類。

子類必須至少定義下面“入口點”部分中定義的方法之一。

應用程序不應直接構造 ?RequestHandler ?對象,子類不應覆蓋 ?__init__? (而是覆蓋初始化)。

入口點

RequestHandler.initialize() → None

子類初始化的鉤子,為每個請求調用。

作為 URLSpec 的第三個參數(shù)傳遞的字典將作為關鍵字參數(shù)提供給 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?等之前的請求開始時調用。

覆蓋此方法以執(zhí)行通用初始化,而不管請求方法如何。

異步支持:使用 ?async def? 或用 ?gen.coroutine? 裝飾此方法以使其異步。 如果此方法返回 ?Awaitable?,則在 ?Awaitable? 完成之前不會繼續(xù)執(zhí)行。

3.1 版新功能:異步支持。

RequestHandler.on_finish() → None

在請求結束后調用。

重寫此方法以執(zhí)行清理、記錄等。此方法是準備的對應方法。 ?on_finish? 可能不會產生任何輸出,因為它是在響應發(fā)送到客戶端之后調用的。

實現(xiàn)以下任一方法(統(tǒng)稱為 HTTP 動詞方法)來處理相應的 HTTP 方法。 可以使用 ?async def? 關鍵字或 ?gen.coroutine? 使這些方法異步。

這些方法的參數(shù)來自 ?URLSpec?:正則表達式中的任何捕獲組都將成為 HTTP 動詞方法的參數(shù)(如果組被命名,則為關鍵字參數(shù),如果未命名,則為位置參數(shù))。

要支持不在此列表中的方法,請覆蓋類變量 SUPPORTED_METHODS:

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

    def propfind(self):
        pass

輸入

?argument?方法提供對 HTML 表單樣式參數(shù)的支持。 這些方法可用于單數(shù)和復數(shù)形式,因為 HTML 表單是模棱兩可的,并且不區(qū)分單數(shù)參數(shù)和包含一個條目的列表。 如果您希望使用其他格式的參數(shù)(例如 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]

返回具有給定名稱的參數(shù)的值。

如果未提供默認值,則認為該參數(shù)是必需的,如果缺少,將引發(fā) ?MissingArgumentError?。

如果參數(shù)多次出現(xiàn)在請求中,我們返回最后一個值。

此方法搜索查詢和正文參數(shù)。

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

返回具有給定名稱的參數(shù)列表。

如果參數(shù)不存在,則返回一個空列表。

此方法搜索查詢和正文參數(shù)。

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

從請求查詢字符串中返回具有給定名稱的參數(shù)的值。

如果未提供默認值,則認為該參數(shù)是必需的,如果缺少,我們將引發(fā) ?MissingArgumentError?。

如果參數(shù)多次出現(xiàn)在 url 中,我們返回最后一個值。

3.2 版中的新功能。

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

返回具有給定名稱的查詢參數(shù)列表。

如果參數(shù)不存在,則返回一個空列表。

3.2 版中的新功能。

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

從請求正文返回具有給定名稱的參數(shù)的值。

如果未提供默認值,則認為該參數(shù)是必需的,如果缺少,我們將引發(fā) ?MissingArgumentError?。

如果參數(shù)多次出現(xiàn)在 url 中,我們返回最后一個值。

3.2 版中的新功能。

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

返回具有給定名稱的主體參數(shù)列表。

如果參數(shù)不存在,則返回一個空列表。

3.2 版中的新功能。

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

從請求中解碼參數(shù)。

該參數(shù)已被百分比解碼,現(xiàn)在是一個字節(jié)字符串。 默認情況下,此方法將參數(shù)解碼為 utf-8 并返回一個 unicode 字符串,但這可能在子類中被覆蓋。

此方法用作 ?get_argument()? 和從 url 中提取并傳遞給 ?get()?/?post()?等值的過濾器。

如果已知,則提供參數(shù)的名稱,但可以為 None(例如,對于 url 正則表達式中的未命名組)。

RequestHandler.request

?tornado.httputil.HTTPServerRequest? 對象包含其他請求參數(shù),例如 標題和正文數(shù)據(jù)。

RequestHandler.path_kwargs

?path_args? 和 ?path_kwargs? 屬性包含傳遞給 HTTP 方法的位置和關鍵字參數(shù)。 這些屬性是在調用這些方法之前設置的,因此這些值在準備期間可用。

輸出

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

為我們的響應設置狀態(tài)碼。

參數(shù):

  • ?status_code (int)? -- 響應狀態(tài)代碼。
  • ?reason (str)? -- 描述狀態(tài)代碼。 如果沒有,它將從 http.client.responses 或“空”填寫。

在 5.0 版更改: 不再驗證響應代碼是否在 ?http.client.responses? 中。

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

設置給定的響應頭名稱和值。

所有標頭值都轉換為字符串(?datetime ?對象根據(jù) ?Date ?表頭的 HTTP 規(guī)范進行格式化)。

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

將給定的塊寫入輸出緩沖區(qū)。

要將輸出寫入網(wǎng)絡,請使用下面的 ?flush()? 方法。

如果給定的塊是一個字典,我們將它寫為 JSON 并將響應的 ?Content-Type? 設置為 ?application/json?。 (如果您想將 JSON 作為不同的 ?Content-Type? 發(fā)送,請在調用 ?write()? 后調用 ?set_header?)。

請注意,由于潛在的跨站點安全漏洞,列表不會轉換為 JSON。 所有 JSON 輸出都應包含在字典中。

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

將當前輸出緩沖區(qū)刷新到網(wǎng)絡。

在 4.0 版更改: 如果沒有給出回調,現(xiàn)在返回 ?Future?。

在 6.0 版更改: 回調參數(shù)已刪除。

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

完成此響應,結束 HTTP 請求。

將一個塊傳遞給 ?finish()? 等效于將該塊傳遞給 ?write()? 然后調用沒有參數(shù)的 ?finish()?。

返回一個 ?Future ?,它可以選擇等待以跟蹤向客戶端發(fā)送的響應。 當所有響應數(shù)據(jù)都已發(fā)送時,此 ?Future ?將解析,如果在發(fā)送所有數(shù)據(jù)之前關閉連接,則會引發(fā)錯誤。

在 5.1 版更改: 現(xiàn)在返回 ?Future ?而不是 ?None?。

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

使用給定參數(shù)呈現(xiàn)模板作為響應。

?render()? 調用了 ?finish()?,因此在它之后不能調用其他輸出方法。

返回一個與?finish?返回的具有相同語義的?Future?。 等待這個 Future?是可選的。

在 5.1 版更改: 現(xiàn)在返回 ?Future?而不是 ?None?。

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

使用給定的參數(shù)生成給定的模板。

我們返回生成的字節(jié)串(utf8 格式)。 要使生成和編寫模板作為響應,請使用上面的 ?render()?。

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

返回要用作默認模板命名空間的字典。

可以被子類覆蓋以添加或修改值。

此方法的結果將與 ?tornado.template? 模塊中的其他默認值和渲染或渲染字符串的關鍵字參數(shù)相結合。

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

將重定向發(fā)送到給定的(可選相對)URL。

如果指定了 ?status ?參數(shù),則該值用作 HTTP 狀態(tài)代碼; 否則根據(jù)永久參數(shù)選擇 301(永久)或 302(臨時)。 默認值為 302(臨時)。

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

將給定的 HTTP 錯誤代碼發(fā)送到瀏覽器。

如果已經調用了 ?flush()?,則不可能發(fā)送錯誤,因此此方法將簡單地終止響應。 如果輸出已寫入但尚未刷新,它將被丟棄并替換為錯誤頁面。

覆蓋 ?write_error()? 以自定義返回的錯誤頁面。 額外的關鍵字參數(shù)被傳遞給 ?write_error?。

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

覆蓋以實現(xiàn)自定義錯誤頁面。

?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

用于呈現(xiàn)已呈現(xiàn)網(wǎng)頁的最終 js 鏈接的默認方法。

在子類控制器中覆蓋此方法以更改輸出。

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

用于渲染網(wǎng)頁的最終嵌入 js 的默認方法。

在子類控制器中覆蓋此方法以更改輸出。

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

用于呈現(xiàn)已呈現(xiàn)網(wǎng)頁的最終 css 鏈接的默認方法。

在子類控制器中覆蓋此方法以更改輸出。

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

用于為渲染網(wǎng)頁渲染最終嵌入 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? 立即可見; 他們直到下一個請求才會出現(xiàn)。

expires 可以是 ?time.time? 返回的數(shù)字時間戳、?time.gmtime? 返回的時間元組或 ?datetime.datetime? 對象。

額外的關鍵字參數(shù)直接在 cookies.Morsel 上設置。

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

刪除具有給定名稱的 cookie。

由于 cookie 協(xié)議的限制,您必須傳遞與設置 cookie 時使用的相同路徑和域來清除 cookie(但無法在服務器端找出給定 cookie 使用了哪些值) .

和 ?set_cookie? 類似,這個方法的效果要等到后面的請求才會看到。

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

刪除用戶隨此請求發(fā)送的所有 cookie。

和 ?set_cookie ?類似,這個方法的效果要等到后面的請求才會看到。

在 3.2 版更改: 添加了路徑和域參數(shù)。

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

如果驗證通過,則返回給定的簽名 cookie,或者無。

解碼后的 cookie 值作為字節(jié)字符串返回(與 ?get_cookie ?不同)。

與 ?get_cookie ?類似,此方法僅返回請求中存在的 cookie。 它在此處理程序中看不到由 ?set_secure_cookie ?設置的傳出 cookie。

在 3.2.1 版更改:添加了 ?min_version? 參數(shù)。 引入 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 ?設置才能使用此方法。 它應該是一個長的、隨機的字節(jié)序列,用作簽名的 HMAC 機密。

要使用此方法讀取 cookie 集,請使用 ?get_secure_cookie()?。

請注意 ?expires_days ?參數(shù)設置瀏覽器中 cookie 的生命周期,但與 ?get_secure_cookie? 的 ?max_age_days? 參數(shù)無關。 None 值將生命周期限制為當前瀏覽器會話。

安全 cookie 可能包含任意字節(jié)值,而不僅僅是 unicode 字符串(與常規(guī) cookie 不同)

和 ?set_cookie類似,這個方法的效果要等到后面的請求才會看到。

在 3.2.1 版更改:添加了?version?參數(shù)。 引入 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 ?的可選值參數(shù)。

在 3.2.1 版更改:添加了?version?參數(shù)。 引入 cookie 版本 2 并將其設為默認值。

應用程序配置

構成 Web 應用程序的請求處理程序的集合。

此類的實例是可調用的,并且可以直接傳遞給 HTTPServer 以服務于應用程序:

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

此類的構造函數(shù)接收一個 ?Rule對象列表或對應于 ?Rule構造函數(shù)參數(shù)的值元組:?(matcher, target, [target_kwargs], [name])?,方括號中的值是可選的。 默認匹配器是 ?PathMatches?,因此也可以使用 ?(regexp, target)? 元組來代替 ?(PathMatches(regexp), target)?。

常見的路由目標是 ?RequestHandler子類,但您也可以使用規(guī)則列表作為目標,從而創(chuàng)建嵌套路由配置:

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

除此之外,您還可以使用嵌套的 ?Router實例、?HTTPMessageDelegate ?子類和可調用對象作為路由目標。

當我們收到請求時,我們按順序遍歷列表并實例化第一個請求類的實例,其正則表達式與請求路徑匹配。 請求類可以指定為類對象或(完全限定的)名稱。

字典可以作為元組的第三個元素 (?target_kwargs?) 傳遞,它將用作處理程序的構造函數(shù)和?initialize?方法的關鍵字參數(shù)。 此模式用于本示例中的 ?StaticFileHandler?(請注意,可以使用下面描述的 ?static_path ?設置自動安裝 ?StaticFileHandler?):

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

我們使用 ?add_handlers方法支持虛擬主機(virtual hosts),該方法將主機的正則表達式作為第一個參數(shù):

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

如果當前請求的主機不匹配,則 ?default_host參數(shù)值與主機的正則表達式匹配。

注意:不使用 TLS 的應用程序可能容易受到 DNS 重新綁定攻擊。 此攻擊與僅偵聽 ?127.0.0.1或其他專用網(wǎng)絡的應用程序特別相關。 必須使用適當?shù)闹鳈C模式(而不是默認的? r'.*'?)來防止這種風險。 ?default_host ?參數(shù)不得用于可能易受 DNS 重新綁定攻擊的應用程序中。

您可以通過將 ?static_path ?設置作為關鍵字參數(shù)發(fā)送來提供靜態(tài)文件。 我們將從 ?/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 服務器。

這是一個方便的別名,用于創(chuàng)建HTTPServer?對象并調用其監(jiān)聽方法。 ?HTTPServer.listen? 不支持的關鍵字參數(shù)被傳遞給 ?HTTPServer構造函數(shù)。 對于高級用途(例如多進程模式),請勿使用此方法; 創(chuàng)建一個 ?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?。

參數(shù):

  • ?request(httputil.HTTPServerRequest) – 當前的 HTTP 請求。
  • ?target_class(RequestHandler) – 一個 RequestHandler 類。
  • ?target_kwargs(dict) -- target_class 構造函數(shù)的關鍵字參數(shù)。
  • ?path_args(list) – target_class HTTP 方法的位置參數(shù),將在處理請求(get、post 或任何其他)時執(zhí)行。
  • ?path_kwargs(dict) -- target_class HTTP 方法的關鍵字參數(shù)。

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 并覆蓋此方法,或將應用程序設置字典中的函數(shù)作為 ?log_function傳遞。

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

指定 URL 和處理程序之間的映射。
參數(shù):

  • ?pattern?:要匹配的正則表達式。 正則表達式中的任何捕獲組都將作為參數(shù)傳遞給處理程序的 get/post等方法(如果命名則按關鍵字,如果未命名則按位置。命名和未命名的捕獲組不能在同一規(guī)則中混合使用)。
  • ?handler?:要調用的 RequestHandler 子類。
  • ?kwargs?(可選):要傳遞給處理程序構造函數(shù)的附加參數(shù)字典。
  • ?name?(可選):此處理程序的名稱, 由 ?reverse_url ?使用。

?URLSpec類也可以在名稱 ?tornado.web.url?下使用。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號