WSGI[1] is not a server, a python module, a framework, an API or any kind of software. It is just an interface specification by which server and application communicate. Both server and application interface sides are specified in the PEP 3333. If an application (or framework or toolkit) is written to the WSGI spec then it will run on any server written to that spec.
这是wsgi.tutorial的解释。WSGI只是一种协议接口,规定好server(可以考虑为nginx,apache) 和 application的交流方式。
Web App
web app其实就是各种框架,flask,Django,bottle,他们至少要提供这么一个callable对象(a function, a method, a class or an instance with an object.call() method),且此对象接收两个必须参数
- environ
经历过古代写cgi的同学应该知道这个变量,其实就是一个字典,里面登记着用户客户端request的基本信息,随便给几个大家感受下,然而wsgi比基础的cgi再多点key-value值
environ points to a dictionary containing CGI like environment ,variables which is populated by the server for each,received request from the client
# Required CGI variables
env['REQUEST_METHOD'] = self.request_method # GET
env['PATH_INFO'] = self.path # /hello
env['SERVER_NAME'] = self.server_name # localhost
env['SERVER_PORT'] = str(self.server_port) # 8888
- start_response
is a callback function supplied by the server ,which takes the HTTP status and headers as arguments
这也是一个callable函数,可以由WSGI container(Middleware)提供,接收HTTP status, 和 一些头部的信息,这个函数的作用最后就是设定http回包的头部信息
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return ['Hello world!']
Middleware
类似的有这些WSGI container: uWSGI, flup, Gunicorn
The thing to remember here, is that your entire web application can be called with that one simple command up above. As such, other functions or classes can wrap around your web application object and do other things before and/or after your web application gets called. That’s really all WSGI middleware is.
这个Middleware的功能一般都放在了WSGI container层做了,上面这句英文解释已经说的很清楚了,这一层会调用web app提供好的application,并在调用前后做一些额外的操作,例如下面的操作。那么Python正好提供了一种技术装饰器 (Decorator)
There is currently WSGI middleware that will:
- Handle web application errors
- Provide session support
- Profile your web application
- Deal with Login authentication
- and Gzip the output
参考一下知乎某个用户的回答:
作者:不求东西 链接
『Middleware』本质上是一个『装饰器 Decorator』,和Application类似它也是一个『Callable对象』,如果它有『call』方法,其签名应该是这样的:def call(app: Application): transformedApp: Application这个Middleware返回的类型是一个被『装饰』过的Application(transformedApp变量),这个transformedApp所依赖的『environ』和『start_response』可以被当前Middleware所在上层的Server/Middleware所注入。再看 这个Middleware的参数,它也是一个Application(app变量),所以Middleware本身的一些附加的逻辑和数据也可以通过app的参数注入到下层的Application里。Middleware是可以嵌套使用的,比如有『mw1』和『mw2』两个Middleware和『app』一个Application,就可以通过mw1(mw2(app))
返回一个新的Application,如果mw1和mw2是相互独立的,嵌套顺序理论上也可以互换。也可以使用Python的『Decorator』语法,直接装饰app:@mw1@mw2def app(environ, start_response): ...