#全面解读tornado

这只是个人的解读以及总结,如有错误,请不吝指正。

##WSGI 首先,说起python的web框架(web framework), 必须要提到的就是WSGI, WSGI并不是python的模块或者框架,而是一种web服务器和web应用间的接口规范。

web服务器,比如Nginx,web应用,就是你自己的应用代码。 /Users/zhouligang/workshop/graphviz/a.png

web应用这边主要实现一个接收两个参数的可调用的对象(函数,类或者有__call__函数的实例)

  • 第一个参数是一个字典,包含该请求的一些信息(比如PATH_INFO: 当前请求的路径, SERVER_PROTOCOL, SERVER_PORT等等)
  • 第二个参数是一个回掉函数,用于将状态码和http头返回给web服务器
# function version
def application(environ, start_response):
    response_body = '\n'.join(['%s: %s' % (k, v) for k, v in sorted(environ.items())])
    status = '200 OK'
    response_headers = [  # start_response 第二个参数,http头,是tuple的数组 
    	('Content-Type', 'text/plain'),
    	('Content-Length', str(len(response_body))
    ]
    start_response(status, response_headers)
    return [response_body.encode()]


# class version
class Application1(object):
	def __init__(self, environ, start_response):
		self.environ = environ
		self.start_response = start_response
	
	def __iter__(self):
		response_body = '\n'.join(['%s: %s' % (k, v) for k, v in sorted(environ.items())])
    	status = '200 OK'
    	response_headers = [  # start_response 第二个参数,http头,是tuple的数组 
    		('Content-Type', 'text/plain'),
    		('Content-Length', str(len(response_body))
    	]
    	start_response(status, response_headers)
    	yield [response_body.encode()]

# class version
Class Application2(object):
	def __call__(self):
		response_body = '\n'.join(['%s: %s' % (k, v) for k, v in sorted(environ.items())])
    	status = '200 OK'
    	response_headers = [  # start_response 第二个参数,http头,是tuple的数组 
    		('Content-Type', 'text/plain'),
    		('Content-Length', str(len(response_body))
    	]
    	start_response(status, response_headers)
    	yield [response_body.encode()]

使用如下方式运行

from wsgiref.simpler_server import make_server

httpd = make_server('localhost', 8000, application)
httpd = make_server('localhost', 8000, Application1)
httpd = make_server('localhost', 8000, Application2())

httpd.serve_forever()

现在打开浏览器访问时,能看到web服务器传给web应该的参数字典都有什么。

如果想在请求不同地址时,返回不同数据时,可以对参数中PATH_INFO进行判断 如:

def gen_response_according_2_path(environ):
	if environ['PATH_INFO']=='/':
		return 'blabla'
	elif ...:
		return 'blabla'
	else:
		return 'blabla'

def application(environ, start_response):
    response_body = gen_response_according2path(environ)
    status = '200 OK'
    response_headers = [  # start_response 第二个参数,http头,是tuple的数组 
    	('Content-Type', 'text/plain'),
    	('Content-Length', str(len(response_body))
    ]
    start_response(status, response_headers)
    return [response_body.encode()]

参考: pep-333 wsgiref wsgi tutorial