Python自学笔记十一、WSGI
来源:互联网 发布:深圳阿里云幕布拍照 编辑:程序博客网 时间:2024/06/06 04:53
PEP 0333 – Python Web Server Gateway Interface 是一种 web server or gateway 和 python web application or framework 之间简单通用的接口,符合这种接口的 application 可运行在所有符合该接口的 server 上。通俗的讲,WSGI 规范了一种简z单的接口,解耦了 server 和 application,使得双边的开发者更加专注自身特性的开发。
Web server/gateway: 即 HTTP Server,处理 HTTP 协议,接受用户 HTTP 请求和提供并发,调用 web application 处理业务逻辑。通常采用 C/C++ 编写,代表:apache, nginx 和 IIS。
Python Web application/framework: 专注业务逻辑的 python 应用或者框架。
The Application/Framework Side
Application/framework 端必须定义一个 callable object,callable object 可以是以下三者之一:
function, method
class
instance with a __call__ method
Callable object 必须满足以下两个条件:
接受两个参数:字典(environ),回调函数(start_response,返回 HTTP status,headers 给 web server)
返回一个可迭代的值
基于 callable function 的 application/framework 样例如下:
def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['This is a python application!']
基于 callable class 的 application/framework 样例如下:
class ApplicationClass(object): def __init__(self, environ, start_response): self.environ = environ self.start_response = start_response def __iter__(self): self.start_response('200 OK', [('Content-type', 'text/plain')]) yield "Hello world!n"
The Server/Gateway Side
Server/gateway 端主要专注 HTTP 层面的业务,重点是接收 HTTP 请求和提供并发。每当收到 HTTP 请求,server/gateway 必须调用 callable object:
接收 HTTP 请求,但是不关心 HTTP url, HTTP method 等
为 environ 提供必要的参数,实现一个回调函数 start_response,并传给 callable object
调用 callable object
我们直接使用支持 WSGI 框架的 wsgiref 库,编写一个样例:
# application/framework sidedef application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['This is a python application!']# server/gateway sideif __name__ == '__main__': from wsgiref.simple_server import make_server server = make_server('0.0.0.0', 8080, application) server.serve_forever()
运行后,对于任意的 url 和 method,本例的返回值均为 ‘This is a python application!’
$curl 127.0.0.1:8080This is a python application! $ curl 127.0.0.1:8080/testThis is a python application!
Middleware: Components that Play Both Sides
Middleware 处于 server/gateway 和 application/framework 之间,对 server/gateway 来说,它相当于 application/framework;对 application/framework 来说,它相当于 server/gateway。每个 middleware 实现不同的功能,我们通常根据需求选择相应的 middleware 并组合起来,实现所需的功能。比如,可在 middleware 中实现以下功能:
1.根据 url 把用户请求调度到不同的 application 中。
2.负载均衡,转发用户请求
3.预处理 XSL 等相关数据
44限制请求速率,设置白名单
本例实现了一个 IPBlacklist 的 middleware:
class IPBlacklistMiddleware(object): def __init__(self, app): self.app = app def __call__(self, environ, start_response): ip_addr = environ.get('HTTP_HOST').split(':')[0] if ip_addr not in ('127.0.0.1'): return forbidden(start_response) return self.app(environ, start_response)def forbidden(start_response): start_response('403 Forbidden', [('Content-Type', 'text/plain')]) return ['Forbidden']def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['This is a python application!']if __name__ == '__main__': from wsgiref.simple_server import make_server application = IPBlacklistMiddleware(application) server = make_server('0.0.0.0', 8080, application) server.serve_forever()
# 从本机测试$ curl 127.0.0.1:8080/testThis is a python application!# 从其它主机测测试 $ curl 10.10.10.2:8080/test Forbidden
Path Dispatching
至此样例的一个不足之处是对于任意的 url 和 method,程序的返回值均为 ‘This is a python application!’,所以我们需要增加 path dispatch 功能。由于 WSGI 框架下的 server/gateway 不处理 url 和 method,所以 url mapping 需由 application/framework 端完成。注意到参数 environ,它包含以下变量:
1.REQUEST_METHOD: 即 HTTP method
2.PATH_INFO: 即 HTTP url
所以 application/framework 可以根据 environ 的 REQUEST_METHOD 和 PATH_INFO 实现 path dispatch,样例如下:
class IPBlacklistMiddleware(object): def __init__(self, app): self.app = app def __call__(self, environ, start_response): ip_addr = environ.get('HTTP_HOST').split(':')[0] if ip_addr not in ('127.0.0.1'): return forbidden(start_response) return self.app(environ, start_response)def dog(start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['This is dog!']def cat(start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['This is cat!']def not_found(start_response): start_response('404 NOT FOUND', [('Content-Type', 'text/plain')]) return ['Not Found']def forbidden(start_response): start_response('403 Forbidden', [('Content-Type', 'text/plain')]) return ['Forbidden']def application(environ, start_response): path = environ.get('PATH_INFO', '').lstrip('/') mapping = {'dog': dog, 'cat': cat} call_back = mapping[path] if path in mapping else not_found return call_back(start_response)if __name__ == '__main__': from wsgiref.simple_server import make_server application = IPBlacklistMiddleware(application) server = make_server('0.0.0.0', 8080, application) server.serve_forever()
- Python自学笔记十一、WSGI
- Python笔记:wsgi简介
- python学习笔记(WSGI)
- python WSGI
- python +wsgi
- Python WSGI
- Python WSGI
- python WSGI
- qt自学笔记(十一)之定时器
- python自学笔记1
- python自学笔记 2
- python自学笔记 3
- python自学笔记 4
- python自学笔记
- Python自学笔记
- python自学笔记 20151126
- python 自学笔记
- python 自学笔记20151215
- 分页综合应用(分页下拉、当前页、上一页、下一页)
- Prim算法另一种形式
- IO流_复制图片的4种方式案例
- python3.5安装Twisted
- 【CodeForces734E】【缩点】Anton and Tree 题解
- Python自学笔记十一、WSGI
- |poj 3311|状压DP|Hie with the Pie
- 关于微服务的两篇文章以及Eventuate
- lost in the city(枚举)
- Javascript闭包(Closure)简化精简版
- 字符编码 ASCII,Unicode 和 UTF-8 概念扫盲
- Zookeeper(三)ZAB协议的两种基本模式:崩溃恢复和广播消息
- C 练习实例28
- Cocos场景遍历与渲染