首先是CGI规范中要求的变量:
- REQUEST_METHOD: HTTP请求方法,'GET', 'POST'等,不能为空
- SCRIPT_NAME: HTTP请求path中的初始部分,用来确定对应哪一个application,当application对应于服务器的根,可以为空
- PATH_INFO: path中剩余的部分,application要处理的部分,可以为空
- QUERY_STRING: HTTP请求中的查询字符串,URL中?后面的内容
- CONTENT_TYPE: HTTP headers中的Content-Type内容
- CONTENT_LENGTH: HTTP headers中的Content-Length内容
- SERVER_NAME和SERVER_PORT: 服务器域名和端口,这两个值和前面的SCRIPT_NAME, PATH_INFO拼起来可以得到完整的URL路径
- SERVER_PROTOCOL: HTTP协议版本,'HTTP/1.0'或'HTTP/1.1'
- HTTP_Variables: 和HTTP请求中的headers对应,比如'User-Agent'写成'HTTP_USER_AGENT'的格式
WSGI规范中还要求environ包含下列成员:
- wsgi.version:一个元组(1, 0),表示WSGI版本1.0
- wsgi.url_scheme:http或者https
- wsgi.input:一个类文件的输入流,application可以通过这个获取HTTP请求的body
- wsgi.errors:一个输出流,当应用程序出错时,可以将错误信息写入这里
- wsgi.multithread:当application对象可能被多个线程同时调用时,这个值需要为True
- wsgi.multiprocess:当application对象可能被多个进程同时调用时,这个值需要为True
- wsgi.run_once:当server期望application对象在进程的生命周期内只被调用一次时,该值为True
我们可以使用python官方库wsgiref实现的server看一下environ的具体内容:
def demo_app(environ, start_response):
from StringIO import StringIO
stdout = StringIO()
print >>stdout, "Hello world!"
print >>stdout
h = environ.items()
h.sort()
for k,v in h:
print >>stdout, k,'=', repr(v)
start_response("200 OK", [('Content-Type','text/plain')])
return [stdout.getvalue()]
if __name__ == '__main__':
from wsgiref.simple_server import make_server
httpd = make_server('', 8000, demo_app)
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
import webbrowser
webbrowser.open('http://localhost:8000/xyz?abc')
httpd.handle_request() # serve one request, then exit
httpd.server_close()
打开的网页会输出environ的具体内容。
使用environ组装请求URL地址:
from urllib.parse import quote
url = environ['wsgi.url_scheme']+'://'
if environ.get('HTTP_HOST'):
url += environ['HTTP_HOST']
else:
url += environ['SERVER_NAME']
if environ['wsgi.url_scheme'] == 'https':
if environ['SERVER_PORT'] != '443':
url += ':' + environ['SERVER_PORT']
else:
if environ['SERVER_PORT'] != '80':
url += ':' + environ['SERVER_PORT']
url += quote(environ.get('SCRIPT_NAME', ''))
url += quote(environ.get('PATH_INFO', ''))
if environ.get('QUERY_STRING'):
url += '?' + environ['QUERY_STRING']
start_resposnestart_response是一个可调用对象,接收两个必选参数和一个可选参数: