WSGI基礎知識(轉)

add by zhj: WSGI全稱Web Server Gateway Interface,即Web網關接口。其實它並非OSI七層協議中的協議,它就是一個接口(即函數)而已,而WSGI規定了該接口的輸入,輸出等,其中輸入是指Python應用程序服務器調用接口時提供的實參包含哪些數據,輸出是指接口必須返回哪些參數給接口調用者(即Python應用程序服務器)。應用程序服務器會直接調用Web框架的WSGI接口,而不是經過socket來調用。說白了,WSGI就是接口的規範而已python

WSGI基礎知識

翻譯自Basics of WSGIhttp://agiliq.com/blog/2013/07/basics-wsgi/
譯文 WSGI基礎知識git

在這篇文章裏,咱們將會寫一個web app,這個app它會服務一些url。咱們將不會使用任何Python框架來寫它。咱們只是去說明一下這些機制的背後原理。github

在開始寫這個web app以前,咱們先來澄清幾個下文將要用到的術語。web

  • Web服務器(Web Server): 當咱們說Web 服務器時,咱們指的是軟件,而不是那些存儲你代碼的硬件機器。這個服務器會接收從客戶端(Web瀏覽器)發送過來的請求並返回一個響應(response)。Web服務器自己並不建立響應,它只負責返回響應。因此,Web服務器就須要同Web應用程序交流,由於Web應用程序它能產生響應。瀏覽器

  • Web應用程序(Web Application):Web服務器從它這裏拿到響應。Web Application的職責就是根據url來建立響應並將響應傳回給Web服務器。而後Web服務器就只是返回這個響應到客戶端而已。服務器

  • WSGI: WSGI是一個接口,它只是一份規範或者說是一系列的規則。WSIG不是一個軟件。架構

WSGI會引發人們的注意是由於Web服務器須要跟Web應用程序通訊。WSGI規定了Web應用程序和Web服務器雙方必須實現的規則,以便讓它們之間可以互相交互。這麼說吧,一個符合WSGI規範的服務器就能夠跟一個符合WSGI規範的Web應用程序通訊。app

在WSGI架構裏,WSGI應用程序必須是一個可調用者(callable),而且這個可調用者(callable)必須被傳遞給Web服務器,這樣無論何時,只要Web服務器接收到客戶端的一個請求,它就能隨時調用Web應用程序。框架

想要了解更多關於爲何WSGI會得以出現的緣由,請參照 WSGI的維基百科socket

如今開始寫咱們的Web應用程序。你暫時只須要所有拷貝下面的代碼便可,咱們稍後會對每一行代碼作詳細解釋以便清楚地知道它們都作了什麼。

#web_application.py
from wsgiref.simple_server import make_server

def application(environ, start_response):
    path = environ.get('PATH_INFO')
    if path == '/':
        response_body = "Index"
    else:
        response_body = "Hello"
    status = "200 OK"
    response_headers = [("Content-Length", str(len(response_body)))]
    start_response(status, response_headers)
    return [response_body]

httpd = make_server(
    '127.0.0.1', 8051, application)

httpd.serve_forever()

這個腳本能夠經過運行命令python web_application.py來執行,接着你能夠在瀏覽器中訪問連接http://127.0.0.1:8051/http://127.0.0.1:8051/abcd。你將看到第一個頁面會返回Index,而第二個頁面返回Hello。

如今,咱們來逐句分析下代碼。

  • Python提供了一個方法叫作make_server。咱們能夠用它來建立一個遵循WSGI規範的基於Python的Web服務器。
  • 咱們建立了一個callable叫作application。你能夠認爲這個callable就是上文所說的Web應用程序。
  • make_server()方法建立了一個遵循WSGI規範的web服務器。這裏的httpd就是Web服務器。
  • make_server()的前兩個參數指定了主機(host)以及Web服務器監聽請求的端口(port)。
  • make_server()的第三個參數是Web應用程序,Web服務器將利用這個參數來獲取響應。
  • 代碼的最後一行經過serve_forever來啓動Web服務器。

無論何時,只要有請求進來,運行在8051端口的Web服務器就會去調用Web應用程序,在咱們這個例子裏,Web應用程序就是callable application.

下面是關於Web應用程序代碼的細節。

  • 爲了能和WSGI的Web服務器交互,Web應用程序一樣也必須遵循WSGI規範。
  • 服務器調用它時須要兩個參數。因此,它必須接收兩個參數,這是Web應用程序遵循WSGI規範的第一個條件。
  • 傳給它的第一個參數是包含了許多關於請求(request)信息的一個變量。在咱們這個例子裏,咱們用它來讀取請求的路徑。
  • 傳給它的第二個參數是一個callable。應用程序必須利用這個callable來通知服務器關於響應的狀態以及設定各類報頭(headers)。這是Web應用程序遵循WSGI規範的第二個條件。
  • 咱們的應用程序知足了遵循WSGI規範所要求的兩個條件。
  • 最後,應用程序返回一個響應給WSGI服務器。
  • 而後,服務器最終會轉發這個響應給客戶端。

編輯:

我以前在application的代碼裏忽略了一件事,defnull童鞋在reddit上指出了個人錯誤。

application的最後一行不能返回response_body,正確的狀況是它應該返回[response_body]。緣由是:

  • WSGI服務器指望從應用程序返回一個iterable而後它會將這個iterable的每個元素以一種無緩衝的方式發送給客戶端。
  • 若是咱們堅持返回response_body,那麼response_body是一個string同時也是一個iterable,這樣的話咱們的代碼確實還能正常工做不會報錯。可是同時也使得response_body中的內容將會被一個字符一個字符地傳遞。
  • 然而,若是咱們返回的是[response_body], 在這裏,這個iterable是一個list, 這個list只有惟一一個元素即response_body字符串。這樣,在咱們這個例子裏,整個response_body就只須要被傳遞一次。
  • 這就是爲何咱們應該返回[response_body]而不是response_body。上面的代碼我已經改過來了。

你應該讀讀這篇WSGI來了解更多關於WSGI。

譯者注

  • 更新時間:2014-11-28
  • 本人翻譯的初衷是爲了自身學習和記錄,翻譯很差的地方,還望讀者見諒.
相關文章
相關標籤/搜索