WSGI(Web Server Gateway Interface)既不是一个服务器,也不是一个Python模块或者框架,它是是服务器和Python 开发的web应用程序之间的一个接口标准。该标准包含了两方面:一面是服务器需要实现的,另一面是应用需要是实现的。关于它的详细介绍可以参看PEP 3333。
下面对WSGI做个简单标准做个很简单的介绍以及使用Python的一个WSGI内建实现一个WSGI Hello World程序。
WSGI app 可以是函数、模块、类等,只要表示它的对象能被直接调用,例如一个实现了__call__
方法的类。该对象接收两个位置参数,为了方便演示,可以将这两个参数分别命名为environ
以及start_response
,服务器会通过result = app(environ, start_response)
的形式调用它。
其中,environ
是一个保存了CGI形式的环境变量的字典,而且该字典必须是python内建字典,而不能是内建字典的其他子类或者类字典的其他对象;start_response
是一个接收两个不可省略的位置参数的可调用的对象,这两个位置参数分别是HTTP状态码和应答头。假设这两个位置参数是status, response_headers
,在App中调用该对象的方法是start_response(status, response_headers)
。start_response
返回一个需要一个形如write(data)
的可调用对象,该对象接收的一个位置参数data
是一个bytestring
,他是应答体的一部分。
下面的表格列出了部分字典中可能包含的字段内容,完整的字段介绍可参看PEP 3333,这些内容由服务器负责设置:
Name(key) | Description |
---|---|
REQUEST_METHOD | HTTP 请求方法,如GET\POST |
SCRIPT_NAME | app 所对应的在URL中的路径,可以为空,如果app所在位置为服务器的根目录 |
PATH_INFO | 请求URL路径中确定资源位置的部分,他与SCRIPT_NAME一起构成了完整的请求路径 |
QUERY_STRING | 请求参数,即URL中?后面的那部分 |
CONTENT_TYPE | 请求头中Content-Type 字段的内容 |
CONTENT_LENGTH | 请求头中Content-Length字段的内容 |
SERVER_NAME, SERVER_PORT | 当与SCRIPT_NAME 以及 PATH_INFO合在一起的时候,可以用补全URL |
SERVER_PROTOCOL | 客户端发送该请求所使用的HTTP协议版本 |
WSGI app 返回一个可迭代的包含0到多个的bytestring的对象,这个对象可以是列表、生成器等,只要这个对象能让服务器迭代获取0到多个bytestring。调用WSGI app的服务器会一非缓冲的方式,将app返回的对象的内容迭代发送给客户端,如果需要缓冲,则需要app自己去实现,例如,如果返回的是一个字符串,可以将它构造成一个包含该字符串的列表,这样服务器只迭代一次(因为整个列表只包含一个字符串)而不是迭代整个字符串长度的次数。
下面举个栗子:
def application (
# 一个包含CGI样式环境变量的字典,该字典的内容服务器会负责填充
environ,
# 服务器传进来的一个的接收HTTP状态码和应答首部作为参数的可调用对象
start_response
):
# 处理请求并生成返回内容
response_body = 'Hello World, Here is a WSGI app'
# HTTP 状态码
status = '200 OK'
# HTTP 设置客户端需要的响应首部
response_headers = [
('Content-Type', 'text/plain'),
('Content-Length', str(len(response_body)))
]
# 使用服务器提供的可调用对象将状态信息发送给服务
start_response(status, response_headers)
# 返回一个可迭代的对象,由于服务器不负责缓冲,这里使用列表进行缓冲操作
return [response_body]
以上就是一个非常简单的WSGI app了。使用Python 自带的一个自带的一个WSGI参考实现的简单服务器wsgiref,可以运行我们的Demo。
使用任意文本编辑器,输入以下内容:
#!/usr/bin/env python
from wsgiref.simple_server import make_server
# 开发WSGI app
def application (
# 一个包含CGI样式环境变量的字典,该字典的内容服务器会负责填充
environ,
# 服务器传进来的一个的接收HTTP状态码和应答首部作为参数的可调用对象
start_response
):
# 处理请求并生成返回内容
response_body = 'Hello World, Here is a WSGI app'
# HTTP 状态码
status = '200 OK'
# HTTP 设置客户端需要的响应首部
response_headers = [
('Content-Type', 'text/plain'),
('Content-Length', str(len(response_body)))
]
# 使用服务器提供的可调用对象将状态信息发送给服务
start_response(status, response_headers)
# 返回一个可迭代的对象,由于服务器不负责缓冲,这里使用列表进行缓冲操作
return [response_body]
# 初始化服务器
httpd = make_server('localhost', 8051, application)
# 启动服务器监听
httpd.serve_forever()
将该文件保存成.py后缀的任意名字文件,如wsgi_demo.py
,打开命令行进入到存放该文件的文件夹执行python wsgi_demo.py
,在浏览器地址栏输入http://localhost:8051
即可看到服务器返回的内容。
本文首发于个人公众号TensorBoy。如果你觉得内容还不错,欢迎分享并关注我的公众号TensorBoy,扫描下方二维码获取更多精彩原创内容!