WSGI协议介绍和简单实现

Published:

WSGI是什么

WSGI是一种协议,规定Web服务器如何与Web应用程序通信。

为什么需要使用WSGI

在开发Web应用程序时,只需要关注业务逻辑,HTTP协议层面相关的事情就交给Web服务器处理。那么Web服务器要知道如何与Web程序通信,就需要一种规范来定义,这种规范就是WSGI协议。WSGI协议类似于Java中的Servlet规范。

如何实现WSGI

WSGI协议包含两个实体:服务器(Server)或网关(Gateway)和应用程序(application)或框架(framework)。

WSGI应用程序实现

WSGI对应用程序的要求有3个:

  • 实现一个可调用对象(可调用对象可以是一个函数、类或实现__call__方法的类实例)。
  • 可调用对象接收两个参数:environ(一个字典,包含HTTP信息和WSGI环境信息)、start_response(一个响应请求的函数)。
  • 返回一个iterable(可迭代对象)。

下面是一个简单的WSGI应用程序示例代码:

# app.py
def application(environ, start_response):
    status = '200 OK'
    headers = [('Content-type', 'text/plain')]
    start_response(status, headers)
    return ['Hello, world!']

上述代码中,application是一个可调用对象,接收两个参数:environ和start_response,并返回一个包含响应体内容的可迭代对象。

WSGI服务器实现

WSGI对服务器的要求:

  • 接收HTTP请求,处理environ字典变量。
  • 定义write和start_response函数。
  • 调用应用程序提供的可调用对象,传入environ和start_response函数。

下面是一个简单的WSGI服务器示例代码,使用Python内置的wsgiref模块:

# server.py
from wsgiref.simple_server import make_server

def application(environ, start_response):
    status = '200 OK'
    headers = [('Content-type', 'text/plain')]
    start_response(status, headers)
    return ['Hello, world!']

httpd = make_server('', 8000, application)
print("Serving on port 8000...")

httpd.serve_forever()

上述代码中,make_server函数用于创建一个WSGI服务器,接收三个参数:host、port和application。最后调用serve_forever方法启动服务器,开始监听端口并等待HTTP请求。

可以将上述两份代码保存为两个独立的Python文件,并在终端中分别运行python app.py和python server.py来启动WSGI应用程序和服务器。运行成功后,在浏览器中输入http://localhost:8000即可访问应用程序返回的”Hello, World!”响应。

中间件实现

中间件(Middleware)可以运行于服务器和应用程序之间, 可以用于处理HTTP请求和响应。 对于服务器而言,中间件可以对HTTP请求进行预处理,例如进行鉴权、请求的路由转发等;对于应用程序而言,中间件可以对HTTP响应进行后处理,例如添加响应头、对响应体进行压缩等。

以下是一个简单的WSGI中间件示例代码:

# middleware.py
class Middleware:
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        # 修改environ
        environ['example_key'] = 'example_value'

        # 调用应用程序
        response = self.app(environ, start_response)

        # 修改响应
        response.append(b" from middleware")

        return response

这个中间件的作用是将一个名为 example_key 的键值对添加到 WSGI 环境变量字典中,并在应用程序响应的末尾追加一些文本。应用程序可以通过访问 environ[‘example_key’] 来访问中间件添加的值。

要使用这个中间件,需要在创建应用程序对象之后将其传递给中间件的构造函数:

from app import application

application = Middleware(application)

补充:WSGI、uwsgi和uWSGI之间的区别

WSGI是一种协议,规定web server如何跟web application通信。

uwsgi是一种通信协议,是uWSGI服务器的独占协议。

uWSGI是一个Web服务器,它实现了WSGI、uwsgi和http协议。与其他Web服务器相比,uWSGI的性能很高,可以支持多种编程语言(如Python、Perl、Ruby等)和多种协议(如WSGI、FastCGI、SCGI等),同时还支持多种方式的部署和扩展,是一个非常灵活和强大的Web服务器。