记一次WSGI入门学习
程序员文章站
2022-03-23 18:23:50
...
WSIG
介绍
WSGI全称:web server gateway interface,web服务器的网关接口,是web底层和app之间的解耦的协议,耦合度:大致来说,就是彼此之间的联系。类似于一种通信协议把,起到了一种桥梁的作用。比如,web server和app(flask等)。
工作流程
1、服务器web server :
服务器接受到客户端发来的request之后,提供自己的环境变量还有request(请求方法,url,内容)给app
2、app(application)就是web框架
app里面形成一个回调函数start_response供WSGI调用,参数为environ,start_response
今天看源码发现,这句话是不对的,是WSGI里面生成好环境,还有start_response,供app调用
下面这张流程图是对的
简易实现
- app应用程序端
def application(environ, start_response):
print(environ['PATH_INFO'])
status = '200 OK'
response_header = [('Content-Type', 'text/html')]
start_response(status, response_header)
return ['your path is :{}'.format(environ['PATH_INFO']).encode('utf-8')]
- 服务器端
from wsgiref.simple_server import make_server
from WSGI简单例子.hello import application
httpd = make_server('', 8000, application)
httpd.serve_forever()
- 细节解释:
首先是这边的encode(‘utf-8’),这里必须是byte类型,所以直接用字符串会报错,因为用了format的原因,我们在后面用上utf-8进行编码,另外返回的必须是一个iterable可迭代的,所以这就是为什么要用列表,用yield也是可以的
结果:
用装饰器实现一下路由的过程
前景:
之前一直对路由的工作很是不解,今天遇到了WSGI很巧,正好学了一下。
from wsgiref.simple_server import make_server
class Router:
def __init__(self):
self.routes = {}
def route(self, path):
def decorator(func):
self.routes[path] = func
func()
return decorator
def __call__(self, env, start_response):
path = env['PATH_INFO']
if path in self.routes:
status = '200 OK'
response_header = [('Content-Type', 'text/html')]
start_response(status, response_header)
return self.routes[path]()
else:
status = '404 Not Found'
response_header = [('Content-Type', 'text/html')]
start_response(status, response_header)
return [b'Not find the source']
app = Router()
@app.route('/')
def index():
yield 'this is the index'.encode('utf-8')
@app.route('/home')
def home():
yield b'this is the home'
server = make_server('', 8000, app)
server.serve_forever()
实验结果
总结一下:
我们可以看到,实现一个路由控制还是挺简单的,当然实际当中肯定比我现在做到要复杂。明显的一个弱势就是,头部信息里面的内容怎么处理。
视图函数的返回值是可迭代的,然而我之前,直接用的return 似乎也行,可能是内部代码进行了转换之类的把
_call_这个方法,将类的对象成为一个可以被调用的对象,正如里面的make_server(”, 8000, app)
这让我联想到了app.run()这个函数,似乎调用了werkzeug,说不定这也是一种WSGI的实现,值得去看一下,留个坑
PS:linux 查看某个端口占用
lsof -i:xxx
- 另一个感悟就是,虽然说读源码能够真正的理解,但是对于我新手来说,显然这并不是一个好的选择,也许先知道 些流程是不错的选择。看些大概的源码,不用那么细致。自己实现框架里面的小处理不失为一种好的选择