Tornado提供了一個(gè)具有異步功能的簡(jiǎn)單 Web 框架,允許它擴(kuò)展到大量打開的連接,使其成為長(zhǎng)輪詢的理想選擇。
這是一個(gè)簡(jiǎn)單的“Hello, world”示例應(yīng)用程序:
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()
一般來(lái)說(shuō),?RequestHandler
和 Tornado 中其他地方的方法不是線程安全的。 特別是 ?write()
?、?finish()
? 和 ?flush()
? 等方法只能從主線程調(diào)用。 如果您使用多個(gè)線程,重要的是在完成請(qǐng)求之前使用 ?IOLoop.add_callback
? 將控制權(quán)轉(zhuǎn)移回主線程,或者將其他線程的使用限制為 ?IOLoop.run_in_executor
? 并確保您在執(zhí)行程序中運(yùn)行的回調(diào)不引用 到 Tornado 對(duì)象。
HTTP 請(qǐng)求處理程序的基類。
子類必須至少定義下面“入口點(diǎn)”部分中定義的方法之一。
應(yīng)用程序不應(yīng)直接構(gòu)造 ?RequestHandler
?對(duì)象,子類不應(yīng)覆蓋 ?__init__
? (而是覆蓋初始化)。
子類初始化的鉤子,為每個(gè)請(qǐng)求調(diào)用。
作為 URLSpec 的第三個(gè)參數(shù)傳遞的字典將作為關(guān)鍵字參數(shù)提供給 initialize()。
示例如下:
class ProfileHandler(RequestHandler):
def initialize(self, database):
self.database = database
def get(self, username):
...
app = Application([
(r'/user/(.*)', ProfileHandler, dict(database=database)),
])
在 ?get
?/?post
?等之前的請(qǐng)求開始時(shí)調(diào)用。
覆蓋此方法以執(zhí)行通用初始化,而不管請(qǐng)求方法如何。
異步支持:使用 ?async def
? 或用 ?gen.coroutine
? 裝飾此方法以使其異步。 如果此方法返回 ?Awaitable
?,則在 ?Awaitable
? 完成之前不會(huì)繼續(xù)執(zhí)行。
3.1 版新功能:異步支持。
在請(qǐng)求結(jié)束后調(diào)用。
重寫此方法以執(zhí)行清理、記錄等。此方法是準(zhǔn)備的對(duì)應(yīng)方法。 ?on_finish
? 可能不會(huì)產(chǎn)生任何輸出,因?yàn)樗窃陧憫?yīng)發(fā)送到客戶端之后調(diào)用的。
實(shí)現(xiàn)以下任一方法(統(tǒng)稱為 HTTP 動(dòng)詞方法)來(lái)處理相應(yīng)的 HTTP 方法。 可以使用 ?async def
? 關(guān)鍵字或 ?gen.coroutine
? 使這些方法異步。
這些方法的參數(shù)來(lái)自 ?URLSpec
?:正則表達(dá)式中的任何捕獲組都將成為 HTTP 動(dòng)詞方法的參數(shù)(如果組被命名,則為關(guān)鍵字參數(shù),如果未命名,則為位置參數(shù))。
要支持不在此列表中的方法,請(qǐng)覆蓋類變量 SUPPORTED_METHODS:
class WebDAVHandler(RequestHandler):
SUPPORTED_METHODS = RequestHandler.SUPPORTED_METHODS + ('PROPFIND',)
def propfind(self):
pass
?argument
?方法提供對(duì) HTML 表單樣式參數(shù)的支持。 這些方法可用于單數(shù)和復(fù)數(shù)形式,因?yàn)?HTML 表單是模棱兩可的,并且不區(qū)分單數(shù)參數(shù)和包含一個(gè)條目的列表。 如果您希望使用其他格式的參數(shù)(例如 JSON),請(qǐng)自己解析 ?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.
如果指定的 cookie 不存在,則返回默認(rèn)值。
返回具有給定名稱的參數(shù)的值。
如果未提供默認(rèn)值,則認(rèn)為該參數(shù)是必需的,如果缺少,將引發(fā) ?MissingArgumentError
?。
如果參數(shù)多次出現(xiàn)在請(qǐng)求中,我們返回最后一個(gè)值。
此方法搜索查詢和正文參數(shù)。
返回具有給定名稱的參數(shù)列表。
如果參數(shù)不存在,則返回一個(gè)空列表。
此方法搜索查詢和正文參數(shù)。
從請(qǐng)求查詢字符串中返回具有給定名稱的參數(shù)的值。
如果未提供默認(rèn)值,則認(rèn)為該參數(shù)是必需的,如果缺少,我們將引發(fā) ?MissingArgumentError
?。
如果參數(shù)多次出現(xiàn)在 url 中,我們返回最后一個(gè)值。
3.2 版中的新功能。
返回具有給定名稱的查詢參數(shù)列表。
如果參數(shù)不存在,則返回一個(gè)空列表。
3.2 版中的新功能。
從請(qǐng)求正文返回具有給定名稱的參數(shù)的值。
如果未提供默認(rèn)值,則認(rèn)為該參數(shù)是必需的,如果缺少,我們將引發(fā) ?MissingArgumentError
?。
如果參數(shù)多次出現(xiàn)在 url 中,我們返回最后一個(gè)值。
3.2 版中的新功能。
返回具有給定名稱的主體參數(shù)列表。
如果參數(shù)不存在,則返回一個(gè)空列表。
3.2 版中的新功能。
從請(qǐng)求中解碼參數(shù)。
該參數(shù)已被百分比解碼,現(xiàn)在是一個(gè)字節(jié)字符串。 默認(rèn)情況下,此方法將參數(shù)解碼為 utf-8 并返回一個(gè) unicode 字符串,但這可能在子類中被覆蓋。
此方法用作 ?get_argument()
? 和從 url 中提取并傳遞給 ?get()
?/?post()
?等值的過(guò)濾器。
如果已知,則提供參數(shù)的名稱,但可以為 None(例如,對(duì)于 url 正則表達(dá)式中的未命名組)。
?tornado.httputil.HTTPServerRequest
? 對(duì)象包含其他請(qǐng)求參數(shù),例如 標(biāo)題和正文數(shù)據(jù)。
?path_args
? 和 ?path_kwargs
? 屬性包含傳遞給 HTTP 方法的位置和關(guān)鍵字參數(shù)。 這些屬性是在調(diào)用這些方法之前設(shè)置的,因此這些值在準(zhǔn)備期間可用。
為我們的響應(yīng)設(shè)置狀態(tài)碼。
參數(shù):
status_code (int)
? -- 響應(yīng)狀態(tài)代碼。reason (str)
? -- 描述狀態(tài)代碼。 如果沒(méi)有,它將從 http.client.responses 或“空”填寫。在 5.0 版更改: 不再驗(yàn)證響應(yīng)代碼是否在 ?http.client.responses
? 中。
設(shè)置給定的響應(yīng)頭名稱和值。
所有標(biāo)頭值都轉(zhuǎn)換為字符串(?datetime
?對(duì)象根據(jù) ?Date
?表頭的 HTTP 規(guī)范進(jìn)行格式化)。
添加給定的響應(yīng)表頭和值。
與 ?set_header
? 不同,?add_header
? 可以被多次調(diào)用以返回同一個(gè)表頭的多個(gè)值。
清除傳出標(biāo)頭,撤消先前的set_header
調(diào)用。
請(qǐng)注意,此方法不適用于 ?add_header
? 設(shè)置的多值表頭。
覆蓋它以在請(qǐng)求開始時(shí)設(shè)置 HTTP 表頭。
例如,這是設(shè)置自定義服務(wù)器表頭的地方。 請(qǐng)注意,在請(qǐng)求處理的正常流程中設(shè)置此類表頭可能無(wú)法滿足您的要求,因?yàn)樵阱e(cuò)誤處理期間可能會(huì)重置表頭。
將給定的塊寫入輸出緩沖區(qū)。
要將輸出寫入網(wǎng)絡(luò),請(qǐng)使用下面的 ?flush()
? 方法。
如果給定的塊是一個(gè)字典,我們將它寫為 JSON 并將響應(yīng)的 ?Content-Type
? 設(shè)置為 ?application/json
?。 (如果您想將 JSON 作為不同的 ?Content-Type
? 發(fā)送,請(qǐng)?jiān)谡{(diào)用 ?write()
? 后調(diào)用 ?set_header
?)。
請(qǐng)注意,由于潛在的跨站點(diǎn)安全漏洞,列表不會(huì)轉(zhuǎn)換為 JSON。 所有 JSON 輸出都應(yīng)包含在字典中。
將當(dāng)前輸出緩沖區(qū)刷新到網(wǎng)絡(luò)。
在 4.0 版更改: 如果沒(méi)有給出回調(diào),現(xiàn)在返回 ?Future
?。
在 6.0 版更改: 回調(diào)參數(shù)已刪除。
完成此響應(yīng),結(jié)束 HTTP 請(qǐng)求。
將一個(gè)塊傳遞給 ?finish()
? 等效于將該塊傳遞給 ?write()
? 然后調(diào)用沒(méi)有參數(shù)的 ?finish()
?。
返回一個(gè) ?Future
?,它可以選擇等待以跟蹤向客戶端發(fā)送的響應(yīng)。 當(dāng)所有響應(yīng)數(shù)據(jù)都已發(fā)送時(shí),此 ?Future
?將解析,如果在發(fā)送所有數(shù)據(jù)之前關(guān)閉連接,則會(huì)引發(fā)錯(cuò)誤。
在 5.1 版更改: 現(xiàn)在返回 ?Future
?而不是 ?None
?。
使用給定參數(shù)呈現(xiàn)模板作為響應(yīng)。
?render()
? 調(diào)用了 ?finish()
?,因此在它之后不能調(diào)用其他輸出方法。
返回一個(gè)與?finish
?返回的具有相同語(yǔ)義的?Future
?。 等待這個(gè) Future
?是可選的。
在 5.1 版更改: 現(xiàn)在返回 ?Future
?而不是 ?None
?。
使用給定的參數(shù)生成給定的模板。
我們返回生成的字節(jié)串(utf8 格式)。 要使生成和編寫模板作為響應(yīng),請(qǐng)使用上面的 ?render()
?。
返回要用作默認(rèn)模板命名空間的字典。
可以被子類覆蓋以添加或修改值。
此方法的結(jié)果將與 ?tornado.template
? 模塊中的其他默認(rèn)值和渲染或渲染字符串的關(guān)鍵字參數(shù)相結(jié)合。
將重定向發(fā)送到給定的(可選相對(duì))URL。
如果指定了 ?status
?參數(shù),則該值用作 HTTP 狀態(tài)代碼; 否則根據(jù)永久參數(shù)選擇 301(永久)或 302(臨時(shí))。 默認(rèn)值為 302(臨時(shí))。
將給定的 HTTP 錯(cuò)誤代碼發(fā)送到瀏覽器。
如果已經(jīng)調(diào)用了 ?flush()
?,則不可能發(fā)送錯(cuò)誤,因此此方法將簡(jiǎn)單地終止響應(yīng)。 如果輸出已寫入但尚未刷新,它將被丟棄并替換為錯(cuò)誤頁(yè)面。
覆蓋 ?write_error()
? 以自定義返回的錯(cuò)誤頁(yè)面。 額外的關(guān)鍵字參數(shù)被傳遞給 ?write_error
?。
覆蓋以實(shí)現(xiàn)自定義錯(cuò)誤頁(yè)面。
?write_error
?可以像往常一樣調(diào)用 ?write
?、?render
?、?set_header
?等來(lái)產(chǎn)生輸出。
如果此錯(cuò)誤是由未捕獲的異常(包括 HTTPError)引起的,則 ?exc_info
?三元組將以 ?kwargs["exc_info"]
? 的形式提供。 請(qǐng)注意,對(duì)于 ?sys.exc_info()
? 或 ?traceback.format_exc
? 等方法而言,此異??赡懿皇恰爱?dāng)前”異常。
重置此響應(yīng)的所有表頭和內(nèi)容。
用于呈現(xiàn)已呈現(xiàn)網(wǎng)頁(yè)的最終 js 鏈接的默認(rèn)方法。
在子類控制器中覆蓋此方法以更改輸出。
用于渲染網(wǎng)頁(yè)的最終嵌入 js 的默認(rèn)方法。
在子類控制器中覆蓋此方法以更改輸出。
用于呈現(xiàn)已呈現(xiàn)網(wǎng)頁(yè)的最終 css 鏈接的默認(rèn)方法。
在子類控制器中覆蓋此方法以更改輸出。
用于為渲染網(wǎng)頁(yè)渲染最終嵌入 css 的默認(rèn)方法。
在子類控制器中覆蓋此方法以更改輸出。
RequestHandler.get_cookie(name: str, default: Optional[str] = None) → Optional[str]
返回具有給定名稱的請(qǐng)求 cookie 的值。
如果指定的 cookie 不存在,則返回默認(rèn)值。
此方法僅返回請(qǐng)求中存在的 cookie。 它看不到由 ?set_cookie
? 在此處理程序中設(shè)置的傳出 cookie。
使用給定選項(xiàng)設(shè)置傳出 cookie 名稱/值。
新設(shè)置的 cookie 不會(huì)通過(guò) ?get_cookie
? 立即可見(jiàn); 他們直到下一個(gè)請(qǐng)求才會(huì)出現(xiàn)。
expires 可以是 ?time.time
? 返回的數(shù)字時(shí)間戳、?time.gmtime
? 返回的時(shí)間元組或 ?datetime.datetime
? 對(duì)象。
額外的關(guān)鍵字參數(shù)直接在 cookies.Morsel 上設(shè)置。
刪除具有給定名稱的 cookie。
由于 cookie 協(xié)議的限制,您必須傳遞與設(shè)置 cookie 時(shí)使用的相同路徑和域來(lái)清除 cookie(但無(wú)法在服務(wù)器端找出給定 cookie 使用了哪些值) .
和 ?set_cookie
? 類似,這個(gè)方法的效果要等到后面的請(qǐng)求才會(huì)看到。
刪除用戶隨此請(qǐng)求發(fā)送的所有 cookie。
和 ?set_cookie
?類似,這個(gè)方法的效果要等到后面的請(qǐng)求才會(huì)看到。
在 3.2 版更改: 添加了路徑和域參數(shù)。
如果驗(yàn)證通過(guò),則返回給定的簽名 cookie,或者無(wú)。
解碼后的 cookie 值作為字節(jié)字符串返回(與 ?get_cookie
?不同)。
與 ?get_cookie
?類似,此方法僅返回請(qǐng)求中存在的 cookie。 它在此處理程序中看不到由 ?set_secure_cookie
?設(shè)置的傳出 cookie。
在 3.2.1 版更改:添加了 ?min_version
? 參數(shù)。 引入 cookie 版本 2; 默認(rèn)情況下接受版本 1 和 2。
返回安全 cookie 的簽名密鑰版本。
版本以 int 形式返回。
對(duì) cookie 進(jìn)行簽名和時(shí)間戳記,使其無(wú)法被偽造。
您必須在應(yīng)用程序中指定 ?cookie_secret
?設(shè)置才能使用此方法。 它應(yīng)該是一個(gè)長(zhǎng)的、隨機(jī)的字節(jié)序列,用作簽名的 HMAC 機(jī)密。
要使用此方法讀取 cookie 集,請(qǐng)使用 ?get_secure_cookie()
?。
請(qǐng)注意 ?expires_days
?參數(shù)設(shè)置瀏覽器中 cookie 的生命周期,但與 ?get_secure_cookie
? 的 ?max_age_days
? 參數(shù)無(wú)關(guān)。 None 值將生命周期限制為當(dāng)前瀏覽器會(huì)話。
安全 cookie 可能包含任意字節(jié)值,而不僅僅是 unicode 字符串(與常規(guī) cookie 不同)
和 ?set_cookie
類似,這個(gè)方法的效果要等到后面的請(qǐng)求才會(huì)看到。
在 3.2.1 版更改:添加了?version
?參數(shù)。 引入 cookie 版本 2 并將其設(shè)為默認(rèn)值。
對(duì)字符串進(jìn)行簽名和時(shí)間戳記,使其不能被偽造。
通常通過(guò) ?set_secure_cookie
?使用,但作為非 cookie 使用的單獨(dú)方法提供。 要解碼未存儲(chǔ)為 cookie 的值,請(qǐng)使用 ?get_secure_cookie
?的可選值參數(shù)。
在 3.2.1 版更改:添加了?version
?參數(shù)。 引入 cookie 版本 2 并將其設(shè)為默認(rèn)值。
構(gòu)成 Web 應(yīng)用程序的請(qǐng)求處理程序的集合。
此類的實(shí)例是可調(diào)用的,并且可以直接傳遞給 HTTPServer 以服務(wù)于應(yīng)用程序:
application = web.Application([
(r"/", MainPageHandler),
])
http_server = httpserver.HTTPServer(application)
http_server.listen(8080)
ioloop.IOLoop.current().start()
此類的構(gòu)造函數(shù)接收一個(gè) ?Rule
對(duì)象列表或?qū)?yīng)于 ?Rule
構(gòu)造函數(shù)參數(shù)的值元組:?(matcher, target, [target_kwargs], [name])
?,方括號(hào)中的值是可選的。 默認(rèn)匹配器是 ?PathMatches
?,因此也可以使用 ?(regexp, target)
? 元組來(lái)代替 ?(PathMatches(regexp), target)
?。
常見(jiàn)的路由目標(biāo)是 ?RequestHandler
子類,但您也可以使用規(guī)則列表作為目標(biāo),從而創(chuàng)建嵌套路由配置:
application = web.Application([
(HostMatches("example.com"), [
(r"/", MainPageHandler),
(r"/feed", FeedHandler),
]),
])
除此之外,您還可以使用嵌套的 ?Router
實(shí)例、?HTTPMessageDelegate
?子類和可調(diào)用對(duì)象作為路由目標(biāo)。
當(dāng)我們收到請(qǐng)求時(shí),我們按順序遍歷列表并實(shí)例化第一個(gè)請(qǐng)求類的實(shí)例,其正則表達(dá)式與請(qǐng)求路徑匹配。 請(qǐng)求類可以指定為類對(duì)象或(完全限定的)名稱。
字典可以作為元組的第三個(gè)元素 (?target_kwargs
?) 傳遞,它將用作處理程序的構(gòu)造函數(shù)和?initialize
?方法的關(guān)鍵字參數(shù)。 此模式用于本示例中的 ?StaticFileHandler
?(請(qǐng)注意,可以使用下面描述的 ?static_path
?設(shè)置自動(dòng)安裝 ?StaticFileHandler
?):
application = web.Application([
(r"/static/(.*)", web.StaticFileHandler, {"path": "/var/www"}),
])
我們使用 ?add_handlers
方法支持虛擬主機(jī)(virtual hosts),該方法將主機(jī)的正則表達(dá)式作為第一個(gè)參數(shù):
application.add_handlers(r"www\.myhost\.com", [
(r"/article/([0-9]+)", ArticleHandler),
])
如果當(dāng)前請(qǐng)求的主機(jī)不匹配,則 ?default_host
參數(shù)值與主機(jī)的正則表達(dá)式匹配。
注意:不使用 TLS 的應(yīng)用程序可能容易受到 DNS 重新綁定攻擊。 此攻擊與僅偵聽 ?127.0.0.1
或其他專用網(wǎng)絡(luò)的應(yīng)用程序特別相關(guān)。 必須使用適當(dāng)?shù)闹鳈C(jī)模式(而不是默認(rèn)的? r'.*'
?)來(lái)防止這種風(fēng)險(xiǎn)。 ?default_host
?參數(shù)不得用于可能易受 DNS 重新綁定攻擊的應(yīng)用程序中。
您可以通過(guò)將 ?static_path
?設(shè)置作為關(guān)鍵字參數(shù)發(fā)送來(lái)提供靜態(tài)文件。 我們將從 ?/static/ URI
? 提供這些文件(這可以通過(guò) ?static_url_prefix
設(shè)置進(jìn)行配置),我們將從同一目錄提供 ?/favicon.ico
? 和 ?/robots.txt
?。 可以使用 ?static_handler_class
設(shè)置指定 ?StaticFileHandler
的自定義子類。
在 4.5 版更改: 與新的 ?tornado.routing
? 模塊集成。
在給定端口上為此應(yīng)用程序啟動(dòng) HTTP 服務(wù)器。
這是一個(gè)方便的別名,用于創(chuàng)建HTTPServer
?對(duì)象并調(diào)用其監(jiān)聽方法。 ?HTTPServer.listen
? 不支持的關(guān)鍵字參數(shù)被傳遞給 ?HTTPServer
構(gòu)造函數(shù)。 對(duì)于高級(jí)用途(例如多進(jìn)程模式),請(qǐng)勿使用此方法; 創(chuàng)建一個(gè) ?HTTPServer
并直接調(diào)用它的 ?TCPServer.bind/TCPServer.start
? 方法。
請(qǐng)注意,調(diào)用此方法后,您仍然需要調(diào)用 ?IOLoop.current().start()
? 來(lái)啟動(dòng)服務(wù)器。
返回 ?HTTPServer
對(duì)象。
將給定的處理程序附加到我們的處理程序列表中。
主機(jī)模式按照添加的順序依次處理, 將考慮所有匹配模式。
返回可以為應(yīng)用程序和 ?RequestHandler
子類提供請(qǐng)求的 ?HTTPMessageDelegate
?。
參數(shù):
request
(httputil.HTTPServerRequest) – 當(dāng)前的 HTTP 請(qǐng)求。target_class
(RequestHandler) – 一個(gè) RequestHandler 類。target_kwargs
(dict) -- target_class 構(gòu)造函數(shù)的關(guān)鍵字參數(shù)。path_args
(list) – target_class HTTP 方法的位置參數(shù),將在處理請(qǐng)求(get、post 或任何其他)時(shí)執(zhí)行。path_kwargs
(dict) -- target_class HTTP 方法的關(guān)鍵字參數(shù)。返回名為 name 的處理程序的 URL 路徑
該處理程序必須作為命名的 ?URLSpec
?添加到應(yīng)用程序中。
Args 將替換 ?URLSpec
?正則表達(dá)式中的捕獲組。 如有必要,它們將被轉(zhuǎn)換為字符串,編碼為 utf8 并轉(zhuǎn)義 url。
將完成的 HTTP 請(qǐng)求寫入日志。
默認(rèn)情況下寫入 python 根記錄器。 要更改此行為,請(qǐng)繼承 Application 并覆蓋此方法,或?qū)?yīng)用程序設(shè)置字典中的函數(shù)作為 ?log_function
傳遞。
指定 URL 和處理程序之間的映射。
參數(shù):
pattern
?:要匹配的正則表達(dá)式。 正則表達(dá)式中的任何捕獲組都將作為參數(shù)傳遞給處理程序的 get/post等方法(如果命名則按關(guān)鍵字,如果未命名則按位置。命名和未命名的捕獲組不能在同一規(guī)則中混合使用)。handler
?:要調(diào)用的 RequestHandler 子類。kwargs
?(可選):要傳遞給處理程序構(gòu)造函數(shù)的附加參數(shù)字典。name
?(可選):此處理程序的名稱, 由 ?reverse_url
?使用。?URLSpec
類也可以在名稱 ?tornado.web.url
?下使用。
更多建議: