Twisted的WEB開發

來源:互聯網
上載者:User

標籤:static   定向   lis   dir   指定   網路編程   handler   factory   傳遞   

1   簡介

在WEB開發中,偶爾需要對HTTP協議更多底層細節進行控制,這時的django/web.py等等顯然無法滿足要求,所以只好求助於Twisted了。使用Twisted進行WEB開發,其實更合適的叫法應該是基於HTTP伺服器的開發,因為Twisted相對底層,所以可以控制的東西也比較底層。

在Twisted的技術體系中,這個WEB開發實際上要涉及到HTTPChannel、HTTPFactory、Request三個層次的開發,以下詳訴。

HTTP協議參考 RFC2616 。

 

2   Twisted技術體系

Twisted技術體系包含2個層次:協議和工廠。協議負責串連成功以後對互動的處理,而工廠則是負責串連過程。在HTTP協議中,串連之後還有個產生HTTP請求報文的過程,所以構造出了一個Request對象來處理具體的一個HTTP請求的報文。

在HTTP中的請求報文處理對象是 twisted.web.http.Request 類;HTTP的協議類是 twisted.web.http.HTTPChannel ;HTTP工廠是 twisted.web.http.HTTPFactory 。

 

3   一個簡單的例子

節選自《Twisted網路編程必備》:

from twisted.web import httpclass MyRequestHandler(http.Request):    pages={        ‘/‘:‘<h1>Home</h1>Home Page‘,        ‘/test‘:‘<h1>Test</h1>Test Page‘,        }    def process(self):        if self.pages.has_key(self.path):            self.write(self.pages[self.path])        else:            self.setResponseCode(http.NOT_FOUND)            self.write("<h1>Not Found</h1>Sorry, no such page.")        self.finish()class MyHttp(http.HTTPChannel):    requestFactory=MyRequestHandlerclass MyHttpFactory(http.HTTPFactory):    protocol=MyHttpif __name__=="__main__":    from twisted.internet import reactor    reactor.listenTCP(8000,MyHttpFactory())    reactor.run()

與其他很多架構不同,TwistedWEB只有一個核心的請求處理類Request,各個針對不同的URL的請求也要通過這裡來分發。而這個類只要重載process() 方法就可以了,期間的很多資料都可以通過self來引用。

請求的處理流程也就是判斷對不同URL的不同處理,然後向用戶端寫入響應資訊,並在最後調用關閉請求。步驟如下:

  1. 過濾URL, self.path
  2. self.write(data) 向用戶端寫入資料
  3. self.finish() 關閉響應

 

4   Twisted WEB Request參考

來自分析 twisted.web.http.http.py 原始碼。

 

4.1   請求

包含請求的資料,這裡都是指Request類的成員。

channel :包含上級的HTTP協議對象。

transport :通訊對象。

method :HTTP方法,如GET和POST。

uri :全部請求的URI。

path :具體的請求路徑,不含參數。

args :請求參數,包括URL參數和POST參數。格式如 {‘key‘:[‘val1‘,‘val2‘],} 。

received_headers :請求報文的頭欄位。

received_cookies :請求報文的cookie。

content :請求報文的實體主體,檔案對象。

clientproto :發出請求的用戶端的HTTP版本。

client :?

host :?

getHeader(key) :擷取請求的頭欄位。

getCookie(key) :擷取請求的cookie。

getAllHeaders() :所有請求的頭欄位字典,就是返回received_headers。

getRequestHostname() :請求的host欄位,不含連接埠號碼。

getHost() :原始請求的通訊地址,返回host。

getClientIP() :擷取用戶端IP。

getUser() :擷取basic驗證中的使用者名稱。

getPassword() :擷取basic驗證中的密碼。

getClient() :?

 

4.2   響應

包含響應的資料,這裡都是Request類的成員。

headers :字典,包含響應報文的頭欄位。

cookies :字典,包含響應報文的cookie。

finish() :結束響應報文。

write(data) :向用戶端發送資料,經過了HTTP封裝了。

addCookie(k,v,expires=None,domain=None,path=None,max_age=None,comment=None,secure=None):為響應報文添加一個cookie。

setResponseCode(code,message=None) :設定響應代碼,code參考常量定義。

setHeader(k,v) :設定頭欄位。

redirect(url) :HTTP重新導向。

setLastModified(when) :設定緩衝逾時,when的值為長整型的那個時間。

setETag(etag) :設定緩衝標誌,用於在內容更改時讓使用者有所發覺。

setHost(host,port,ssl=0) :佈建要求地址。用於Proxy 伺服器的重新導向。

 

4.3   常量

沒有響應主體的code:

NO_BODY_CODES=(204,304)

responses=RESPONSES :字典,儲存了各個響應碼的對應提示資訊。

響應報文中的響應碼:

OK=200 :請求處理成功,最常見的響應代碼,但是正因為常見,所以預設就是這個了,也無須設定到setResponseCode。

NOT_MODIFIED=304 :請求的資源沒有沒有修改過,用於瀏覽器緩衝。

BAD_REQUEST=400 :請求報文有語法錯誤。

UNAUTHORIZED=401 :尚未認證,要求使用者輸入認證資訊。

FORBIDDEN=403 :禁止訪問。

NOT_FOUND=404 :請求的資源不存在。

INTERNAL_SERVER_ERROR=500 :伺服器內部錯誤。

NOT_IMPLEMENTED=501 :該功能尚未實現。

BAD_GATEWAY=502 :請求路徑錯誤。

 

4.4   HTTPChannel

建構函式無參數,處理HTTP報文。

requestFactory=Request :指定了請求報文處理工廠。

 

4.5   HTTPFactory

__ini__(logPath=None,timeout=60*60*12) :建構函式可以設定日誌和逾時。

buildProtocol(addr) :內部的構造協議對象的方法,不要調用。

protocol=HTTPChannel :設定協議對象。

 

5   比較完善的開發模式

建立一個Request類的子類作為請求工廠,或者說請求發布器,其中有識別不同的URL並的能力,通過字典找到該URL對應的函數,調用這個函數並傳遞self參數。每個具體的請求處理函數也只有1個request參數,返回資料都是直接寫入request.write()中。

一般來說請求工廠的process()中需要設定響應類型,如網頁的:

self.setHeader("Content-Type","text/html; charset=GB2312")

同時也要在沒有對應的URL時告知用戶端找不到:

self.setResponseCode(http.NOT_FOUND)self.write("<h1>Not Found</h1>Sorry, no such page.")self.finish()

至於self.finish()放在各個請求處理函數中還是放在process(),就是個人愛好問題了。比較推薦放在process()中。

提取請求參數的重點在request.args字典,每個鍵都是映射到一個列表,為了適應HTTP提交中一個鍵對應多個值的情況,當然,你也可以只取第一個值。

 

6   以resource方式提供WEB資源
  1. 每個資源都是 twisted.web.resource.Resource 的子類
  2. 可以自己定義建構函式
  3. 要重載 render(self,request) 方法來響應請求
  4. render 方法中的request對象實際就是Request的執行個體

一個例子:

from twisted.web import resource,static,serverclass HomePage(resource.Resource):    def render(self,request):        request.write("Home Page")        return    def getChild(self,path,request):        return AnotherPage() #另外一個Resource的子類if __name__=="__main__":    from twisted.internet import reactor    root=resource.Resource()    root.putChild(‘‘,HomePage())    root.putChild(‘color‘,ColorRoot())    root.putChild(‘style.css‘,static.File(‘style.css‘))    site=server.Site(root)    reactor.listenTCP(8000,site)    reactor.run()

可以通過各個Resource的構造參數傳入path參數,用以後來尋找下級Resource的參數。

 

Note

關於Resource還有很多細節,但是對本文意義不大,所以略。

 

7   總結

總的來說,用Twisted來開發更適合於開發個架構,而不是直接做WEB應用,有如一直都很少有人直接用 mod_python 來開發WEB應用一樣。

Twisted的WEB開發

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.