1、WSGI是什么
wsgi:Web Server Gateway Interface,是一种协议。用于定义Server与app之间的交互方式。
wsgi把应用分成了3个组件:
1. web server:
主要实现:
1.socket通讯服务器端,监听端口
2.接收、解析http报文
3.读取服务器端的html文档,把读取的html文档response回浏览器,这是静态服务器,如nginx、Apache
4.调用app,返回app执行结果给浏览器。这是动态服务器,如Tomcat。
2. web app
1.一个函数或类的方法
2.遵循固定格式的入口函数_call_()、入参(environ,start_response)、返回值
3. 中间件
1.server与app中间的程序(所以叫中间件)
2.路由
3.流量控制等
ps:
wsgi对web应用的划分太精辟了,对WebServer的理解、应用、url转应用调用等场景的理解豁然开朗。
以前只知道Tomcat,按这个概念套用,也更清楚了。
2、举个例子加深理解
# coding=utf-8
import socket
import sys
class WSGIServer:
def __init__(self):
self.listener=socket.socket()
self.listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
self.listener.bind(('0.0.0.0',8080))
self.listener.listen(1)
print('Serving HTTP 0.0.0.0 port 8080')
self.app=None
self.headers_set=None
def set_app(self,application):
self.app=application
##start_response是服务器提供的函数,供app调用
def start_response(self,status,headers):
self.headers_set=[status,headers]
def serve_forever(self):
while True:
listener=self.listener
client_connection,client_address=listener.accept()
##socket服务器端,接收数据,是http协议的报文
request=client_connection.recv(1024)
print(f'request we received:{request}')
method,path,_=request.split(b' ',2)
environ = {
'wsgi.version': (1, 0),
'wsgi.url_scheme': 'http',
'wsgi.input': request,
'wsgi.errors': sys.stderr,
'wsgi.multithread': False,
'wsgi.multiprocess': False,
'wsgi.run_once': False,
'REQUEST_METHOD': method.decode('utf-8'),
'PATH_INFO': path.decode('utf-8'),
'SERVER_NAME': '127.0.0.1',
'SERVER_PORT': '8080',
}
##server调用app,传入environ(接收到的http报文)和start_response函数
##app内执行传入的start_response函数,并返回结果http内容
app_result=self.app(environ,self.start_response)
##response和app返回的内容构成整个响应的html
response_status,response_headers=self.headers_set
response=f'HTTP/1.1 {response_status}\r\n'
for header in response_headers:
response+=f'{header[0]}:{header[1]}\r\n'
response+='\r\n'
response=response.encode('utf-8')
for data in app_result:
response+=data
##通过网络通讯,返回完整的响应http
client_connection.sendall(response)
client_connection.close()
print('!!!!!!!!one request responsed!!!!!!!!')
if __name__=='__main__':
if len(sys.argv)<2:
sys.exit('argv error')
app_path=sys.argv[1]
module,app=app_path.split(':')
module=__import__(module)
app=getattr(module,app)
server=WSGIServer()
server.set_app(app)
server.serve_forever()
在上边的程序了里:
- init(self):定义socket通讯的服务器端,用来监听端口、接收数据、返回数据。
- serve_forever(self):调用app,生成相应的http报文,在通过socket返回。
- 浏览器:接收服务器返回的http报文,然后渲染展示。
3、看看http请求和相应报文
对程序的部分内容加深理解。
3.1 请求报文
包括:请求的方法、url、客户端程序类型等。
浏览器自动生成并发送的。
GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
3.2 响应报文
注意遵守固定格式,响应头包括协议版本、响应编号、响应结果,
然后,与实际内容中间间隔一个空行。
HTTP/1.1 200 OK
Hello, World!