日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Wsgi研究

發(fā)布時間:2025/7/25 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Wsgi研究 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

FROM:http://blog.kenshinx.me/blog/wsgi-research/

Wsgi研究

Feb 16th, 2012 | Comments

wsgi是一個搞web開發(fā)的pythoner必須了解的內(nèi)容,之前也零散的看過一些文章,但總感覺好多概念很模糊。這幾天抽空又把相關(guān)內(nèi)容好好整理了一下,把筆記貼出來,一些只言片語也許對某些正在研究這個的人有所幫助。
wsgi 是一個 web 組件的接口規(guī)范.,wsgi將 web 組件分為三類: web服務(wù)器,web中間件,web應(yīng)用程序,下圖來自ibm developerworks,很好的說明了三者之間的關(guān)系。

從上圖可以看出來,wsgi基本處理模式為 : WSGI Server -> (WSGI Middleware)*-> WSGI Application 。

下面分別來看這三個組件

WSGI Server/gateway

wsgi server可以理解為一個符合wsgi規(guī)范的webserver,接收request請求,封裝一系列環(huán)境變量,按照wsgi規(guī)范調(diào)用注冊的wsgi app,最后將response返回給客戶端。
文字很難解釋清楚wsgi server到底是什么東西,以及做些什么事情,最直觀的方式還是看wsgiserver的實現(xiàn)代碼。以python自帶的wsgiref為例,wsgiref是按照wsgi規(guī)范實現(xiàn)的一個簡單wsgiserver。它的代碼也不復(fù)雜,下圖是我讀wsgiref代碼后整理的。

通過這個圖可以看出來wsgi server 基本工作流程

  • 服務(wù)器創(chuàng)建socket,監(jiān)聽端口,等待客戶端連接。

  • 當有請求來時,服務(wù)器解析客戶端信息放到環(huán)境變量environ中,并調(diào)用綁定的handler來處理請求。

  • handler解析這個http請求,將請求信息例如method,path等放到environ中。

  • wsgi handler再將一些服務(wù)器端信息也放到environ中,最后服務(wù)器信息,客戶端信息,本次請求信息全部都保存到了環(huán)境變量environ中。

  • wsgi handler 調(diào)用注冊的wsgi app,并將environ和回調(diào)函數(shù)傳給wsgi app

  • wsgi app 將reponse header/status/body 回傳給wsgi handler

  • 最終handler還是通過socket將response信息塞回給客戶端。

  • WSGI Application

    wsgi application就是一個普通的callable對象,當有請求到來時,wsgi server會調(diào)用這個wsgi app。這個對象接收兩個參數(shù),通常為environ,start_response。environ就像前面介紹的,可以理解為環(huán)境變量,跟一次請求相關(guān)的所有信息都保存在了這個環(huán)境變量中,包括服務(wù)器信息,客戶端信息,請求信息。start_response是一個callback函數(shù),wsgi application通過調(diào)用start_response,將response headers/status 返回給wsgi server。此外這個wsgi app會return 一個iterator對象 ,這個iterator就是response body。這么空講感覺很虛,對著下面這個簡單的例子看就明白很多了。

    下面這個例子是一個最簡單的wsgi app,引自http://www.python.org/dev/peps/pep-3333/

    def simple_app(environ, start_response):status = '200 OK'response_headers = [('Content-type', 'text/plain')]start_response(status, response_headers)return [u"This is hello wsgi app".encode('utf8')]

    我們再用wsgiref 作為wsgi server ,然后調(diào)用這個wsgi app,就能直觀看到一次request,response的效果,簡單修改代碼如下:

    from wsgiref.simple_server import make_serverdef simple_app(environ, start_response):status = '200 OK'response_headers = [('Content-type', 'text/plain')]start_response(status, response_headers)return [u"This is hello wsgi app".encode('utf8')]httpd = make_server('', 8000, simple_app) print "Serving on port 8000..." httpd.serve_forever()

    訪問http://127.0.0.1:8000 就能看到效果了。

    此外,上面講到了wsgi app只要是一個callable對象就可以了,因此不一定要是函數(shù),一個實現(xiàn)了call方法的實例也可以,示例代碼如下:

    from wsgiref.simple_server import make_serverclass AppClass:def __call__(self,environ, start_response):status = '200 OK'response_headers = [('Content-type', 'text/plain')]start_response(status, response_headers)return ["hello world!"]app = AppClass() httpd = make_server('', 8000, app) print "Serving on port 8000..." httpd.serve_forever()

    WSGI MiddleWare

    上面的application看起來沒什么意思,感覺沒有太大用,但加上一層層的middleware包裝之后就不一樣了。一堆文字解釋可能還沒有一個demo更容易說明白,我寫了一個簡單Dispatcher Middleware,用來實現(xiàn)URL 路由:

    from wsgiref.simple_server import make_serverURL_PATTERNS= (('hi/','say_hi'),('hello/','say_hello'),)class Dispatcher(object):def _match(self,path):path = path.split('/')[1]for url,app in URL_PATTERNS:if path in url:return appdef __call__(self,environ, start_response):path = environ.get('PATH_INFO','/')app = self._match(path)if app :app = globals()[app]return app(environ, start_response)else:start_response("404 NOT FOUND",[('Content-type', 'text/plain')])return ["Page dose not exists!"]def say_hi(environ, start_response):start_response("200 OK",[('Content-type', 'text/html')])return ["kenshin say hi to you!"]def say_hello(environ, start_response):start_response("200 OK",[('Content-type', 'text/html')])return ["kenshin say hello to you!"]app = Dispatcher()httpd = make_server('', 8000, app) print "Serving on port 8000..." httpd.serve_forever()

    上面的例子可以看出來,middleware 包裝之后,一個簡單wsgi app就有了URL dispatch功能。然后我還可以在這個app外面再加上其它的middleware來包裝它,例如加一個權(quán)限認證的middleware:

    class Auth(object):def __init__(self,app):self.app = appdef __call__(self,environ, start_response):#TODOreturn self.app(environ, start_response)app = Dispatcher() auth_app = Auth(app)httpd = make_server('', 8000, auth_app) print "Serving on port 8000..." httpd.serve_forever()

    經(jīng)過這些middleware的包裝,已經(jīng)有點框架的感覺了。其實基于wsgi的框架,例如paste,pylons就是這樣通過一層層middleware組合起來的。只是一個成熟的框架,這樣的middleware會有很多,例如:

    def configure(app):return ErrorHandlerMiddleware(SessionMiddleware(IdentificationMiddleware(AuthenticationMiddleware(UrlParserMiddleware(app))))))

    只要這些Middleware符合wsgi規(guī)范,甚至還可以在各個框架之間組合重用。例如pylons的認證Middleware可以直接被TurboGears拿去使用。


    總結(jié)

    以上是生活随笔為你收集整理的Wsgi研究的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。