(点击
上方蓝字
,快速关注我们)
来源:人世间(@-人世间-)
www.jianshu.com/p/e7a958bc0f0f
如有好文章投稿,请点击 → 这里了解详情
SimpleHTTPServer模块提供了创建一个http服务的例子。Python web领域里却很少这么做,而是使用了另外一个协议 — WSGI协议。Python的wisgiref模块提供了demo_app,来演示如何使用wsgi协议。
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
()]
demo_app即是一个标准的wsgi app。它接受两个参数,一个包含cgi服务器的环境变量,另外一个参数是一个函数,这个函数也接受两个函数,一个是http状态,另外是http协议的header信息。最后该app返回一个可迭代对象,这个对象即发送给客户端的body内容。demo_app有一些对StringIO的操作,这些都是把environ进行格式化输出。
Python的web框架,都是一个wsgi app。通过自己构造wsgi应用,很容易写出一个框架的骨架。python定义了wsgi,让web框架几乎可以大一统了。下面就来分析,python是如何实现这个协议的。
WSGIServer
python使用WSGIServer和WSGIRequestHandler构建wsgi协议的服务。
class
WSGIServer
(
HTTPServer
)
:
application
=
None
def server_bind
(
self
)
:
HTTPServer
.
server_bind
(
self
)
self
.
setup_environ
()
def setup_environ
(
self
)
:
# 甚至环境变量
env
=
self
.
base_environ
=
{}
env
[
'SERVER_NAME'
]
=
self
.
server_name
env
[
'GATEWAY_INTERFACE'
]
=
'CGI/1.1'
env
[
'SERVER_PORT'
]
=
str
(
self
.
server_port
)
env
[
'REMOTE_HOST'
]
=
''
env
[
'CONTENT_LENGTH'
]
=
''
env
[
'SCRIPT_NAME'
]
=
''
def get_app
(
self
)
:
return
self
.
application
def set_app
(
self
,
application
)
:
self
.
application
=
application
WSGIServer继承HTTPServer,重写了server_bind仿佛,设置了一些专用的环境变量。比较简单,我们也知道,Server只是处理socket连接相关的逻辑,RequestHandler才是处理客户端请求逻辑。
WSGIRequestHandler
WSGIRequestHandler 也不复杂,只有3个方法,get_environ用来设置并返回环境变量的字典,get_stderr用于获取标准错误输出。handle则是重写基类BaseRequestHandler的方法。前文我们也提到,handle用于不同协议处理客户端的入口。
handler
def handle
(
self
)
:
self
.
raw_requestline
=
self
.
rfile
.
readline
()
if
not
self
.
parse_request
()
:
return
handler
=
ServerHandler
(
self
.
rfile
,
self
.
wfile
,
self
.
get_stderr
(),
self
.
get_environ
()
)
handler
.
request_handler
=
self
handler
.
run
(
self
.
server
.
get_app
())
handle方法和BaseHTTPRequestHanler的handle方法所做的类似,解析验证客户端的http的request是否合法。不同的在于,此时会绑定一个ServerHandler的实例对象,并把缓冲可读可写文件句柄,环境变量等传入该类。同时调用这个对象的run方法。其实,我们之前定义的app,恰恰就是传给run方法,通过run方法的包装,实现wsgi协议的通信。
BaseHandler 和 ServerHandler
ServerHandler 来自wsgiref的handlers模块,它继承 BaseHandler类。又一个带base类。BaseHandler主要用于操作WSGI app。run方法就是在该类定义的。
def run
(
self
,
application
)
:
try
:
self
.
setup_environ
()
self
.
result
=
application
(
self
.
environ
,
self
.
start_response
)
self
.
finish_response
()
except
:
try
:
self
.
handle_error
()
except
:
self
.
close
()
raise
run方法最重要的就是调用自定义的wsgi app,并把在finish_reponse方法中把结果send给客户端。
finish_response
def finish_response
(
self
)
:
try
:
if
not
self
.
result_is_file
()
or
not
self
.
sendfile
()
:
for
data
in
self
.
result
:
self
.
write
(
data
)