wsgi应用可以包括函数、方法、类、类实例等。下面讲通过一些代码来说明其实现。这里我们python内置的服务器wsgiref来做演示。
简单函数应用
这里用函数构建了一个app,接收environ和start_response2个参数。并在应用中生成了response_headers和status,作为start_response的参数。最后返回了一个字符串list。
1 | # coding=utf8 |
通过运行文件,可以直接通过curl或者浏览器访问localhost:7000,可以看到输出hello world。
类应用
类应用需要注意的是,传入的是一个类,由类来接受environ和start_response,然后在server中被通过application(self.environ, self.start_response)调用,这时候生成的是一个类实例,而wsgi要求application返回一个可迭代对象,所以类必须就是可迭代的类型,因此需要将类实现成可迭代的,在python中通过__iter__函数实现。1
2
3
4
5
6
7
8
9
10class class_app:
def __init__(self, environ, start_response):
self.environ = environ
self.start_response = start_response
def __iter__(self):
response_headers = [('Content-Type', 'text/html')]
status = '200 OK'
self.start_response(status, response_headers)
yield "<h1>hello world</h1>"
class_app作为application对象传入服务器端提供的函数即可。
实例应用
实例应用是将示例传给服务器,这样就是需要有instance(environ,start_response)的表达形式,在python中需要类中实现__call__函数。1
2
3
4
5
6class instance_app:
def __call__(self, environ, start_response):
response_headers = [('Content-Type', 'text/html')]
status = '200 OK'
start_response(status, response_headers)
return ["<h1>hello world</h1>"]
这里调用是通过instance_app()的方式传入类的实例。
简单的逻辑实现
上面的实现说明了应用的几种不同的实现方式,但是没有涉及到数据的处理,现在实现一个简单的加法计算来说明完整的过程。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32# 参数输入页面文本
cal_page = '''
<form>
cal: <input type="text", name="p1"/>
+
<input type="text", name="p2"/>
submit: <input type="submit", name="submitted"/>
</form>
'''
# 获取参数
def get_param(environ):
params = environ.get('QUERY_STRING') # PEP333中规定QUERY_STRING指表单参数
if params:
return {k: v[0] for k, v in parse_qs(params).items()}
else:
return {}
def cal_app(environ, start_response):
params = get_param(environ)
if params:
result = int(params['p1']) + int(params['p2'])
rsl_str = '{}+{}={}'.format(params['p1'], params['p2'], result)
response_headers = [('Content-Type', 'text/html')]
status = '200 OK'
start_response(status, response_headers)
return [rsl_str.encode('ascii')]
else:
response_headers = [('Content-Type', 'text/html')]
status = '200 OK'
start_response(status, response_headers)
return [cal_page.encode('ascii')]
从上面的实现可以看到cal_app是要传给服务器的应用,通过get_param函数提取参数,在wsgi中使用了cgi形式的environ,规定了:
param | content |
---|---|
QUERY_STRING | The portion of the request URL that follows the “?”, if any. May be empty or absent. |
如果参数为空则返回数字填写页面,有数字则返回计算表达式,这里没有做容错处理,所以两个输入框都要填写东西,否则会出错。效果如下:
综述
以上实现了一些简单的应用,包括了函数、类、实例等,并给出了一个简单计算应用。从这里可以看到只需要实现了对参数和返回值的支持即可以作为应用,而我们常用的框架等就是将这些接口部分进行了封装,屏蔽了这些通用的接口部分,提供更简单的支持方式。另外框架中可能还实现了比如多线程多进程的处理,以及路由,模版渲染等功能,从而能够满足工业应用。