1. 程式人生 > 其它 >什麼是Web伺服器 什麼是WSGI及具體實現例子

什麼是Web伺服器 什麼是WSGI及具體實現例子

以Flask為例:原始碼解析(一):WSGI   轉自:https://www.csdn.net/tags/MtTaEgzsNTYyNzcyLWJsb2cO0O0O.html 2022-03-26 18:35:03

要理解 Flask 的原始碼,必須有一定的 Python 基礎,要熟悉 decorator、magic method、iterator、generator 的概念和用法。還有一點是必須理解 WSGI,下面就講解一些和 WSGI 相關的概念以及用一些程式碼來幫助理解 WSGI。

什麼是Web伺服器

Web伺服器一般指網站伺服器,是指駐留於因特網上某種型別計算機的程式,可以處理瀏覽器等Web客戶端的請求並返回相應響應,也可以放置網站檔案,讓全世界瀏覽;可以放置資料檔案,讓全世界下載。目前最主流的三個Web伺服器是Apache、 Nginx 、IIS。

什麼是WSGI(協議規範)

Web伺服器閘道器介面(Web Server Gateway Interface),是為了讓Web伺服器與Python程式或框架能夠進行資料交流而定義的介面規範。也就是說,只要Web伺服器和Web應用都遵守WSGI協議,那麼Web伺服器和Web應用就可以隨意的組合。

WSGI應用(實現wsgi協議的例項)

根據WSGI的規定,Web應用(或被稱為WSGI應用)必須是一個可呼叫物件(callable object),且要滿足以下三個條件:

  1. 接受environ和start_response兩個引數
  2. 內部呼叫start_response函式來生成狀態碼和響應頭
  3. 返回一個可迭代的響應體

用函式實現一個WSGI應用

def application(environ, start_response):
    """
        environ:包含了請求的所有資訊的字典。
        start_response:用來發起響應的函式,引數是狀態碼、響應頭。
	"""
    start_response('200 OK', [('Content-Type', 'text/plain')])
    yield b'Hello, World!\n'

用類實現一個WSGI應用

class AppClass:
    def __init__(self, environ, start_response):
        self.environ = environ
        self.start_response= start_response

    def __iter__(self):
        self.start_response('200 OK', [('Content-Type', 'text/plain')])
        yield b'Hello, World!\n'

Flask的WSGI實現

class Flask(_PackageBoundObject):
	def wsgi_app(self, environ, start_response):
        ...
         
	def __call__(self, environ, start_response):
        """Shortcut for :attr:`wsgi_app`."""
        return self.wsgi_app(environ, start_response)

WSGI伺服器

簡單實現一個WSGI伺服器(僅用於理解)

from io import BytesIO

def call_application(app, environ):
    status = None
    headers = None
    body = BytesIO()
    
    def start_response(rstatus, rheaders):
        nonlocal status, headers
        status, headers = rstatus, rheaders
        
    app_iter = app(environ, start_response)
    try:
        for data in app_iter:
            assert status is not None and headers is not None, \
                "start_response() was not called"
            body.write(data)
    finally:
        if hasattr(app_iter, 'close'):
            app_iter.close()
    return status, headers, body.getvalue()

environ = {...}
status, headers, body = call_application(app, environ)

使用Python內建模組wsgiref的WSGI伺服器

from wsgiref.simple_server import make_server

def wsgi_app(environ, start_response):
    ...

server = make_server('0.0.0.0', 5000, wsgi_app)
server.serve_forever()

使用WerkZeug模組的WSGI伺服器

用flask run命令執行時,實際上是在執行Werkzeug實現的WSGI伺服器

from werkzeug.serving import run_simple

def wsgi_app(environ, start_response):
    ...
    
run_simple('0.0.0.0', 5000, wsgi_app)

參考

WEB伺服器_百度百科 (baidu.com)
Web Server Gateway Interface - Wikipedia