本文引用自github某大牛的分享
Python基础学完后,免不了要深入到Python的主流Web框架(Python科学计算那部分暂时用不到可以先不管),在学习Flask这些框架的过程中发现它们的底层都是WSGI协议,故决定先啃下WSGI,鉴于目前网上几乎没有(完整的)WSGI中文版,于是大牛干脆自己翻译,这样也有助于加深大牛自己的理解,同时也能够帮助到一些初学者。
PEP 333 - Python Web Server Gateway Interface v1.0 中文版
服务器/网关 端
每一次,当HTTP客户端冲着应用程序发来一个请求,服务器/网关都会调用应用程序可调用者(callable)。为了阐述方便,这里有一个CGI网关,简单的说它就是一个以应用程序对象为参数的函数实现,注意,本例中对错误只做了有限的处理,因为默认情况下没有被捕获到的异常都会被输出到sys.stderr
并被服务器记录下来。
import os, sys
def run_with_cgi(application):
environ = dict(os.environ.items())
environ['wsgi.input'] = sys.stdin
environ['wsgi.errors'] = sys.stderr
environ['wsgi.version'] = (1, 0)
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True
if environ.get('HTTPS', 'off') in ('on', '1'):
environ['wsgi.url_scheme'] = 'https'
else:
environ['wsgi.url_scheme'] = 'http'
headers_set = []
headers_sent = []
def write(data):
if not headers_set:
raise AssertionError("write() before start_response()")
elif not headers_sent:
# 在第一次输出之前发送已存储的报头。
status, response_headers = headers_sent[:] = headers_set
sys.stdout.write('Status: %s\r\n' % status)
for header in response_headers:
sys.stdout.write('%s: %s\r\n' % header)
sys.stdout.write('\r\n')
sys.stdout.write(data)
sys.stdout.flush()
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent:
# 如果报头已发送,则重新抛出原始的异常。
raise exc_info[0], exc_info[1], exc_info[2]
finally:
exc_info = None # 避免死循环。
elif headers_set:
raise AssertionError("Headers already set!")
headers_set[:] = [status, response_headers]
return write
result = application(environ, start_response)
try:
for data in result:
if data: # 在报文体出现前不发送报头。
write(data)
if not headers_sent:
write('') # 如果报文体为空,则发送报头。
finally:
if hasattr(result, 'close'):
result.close()