wsgiref源码解析

您所在的位置:网站首页 专业视频剪辑培训机构证书 wsgiref源码解析

wsgiref源码解析

#wsgiref源码解析| 来源: 网络整理| 查看: 265

wsgiref是PEP 333定义的wsgi规范的范例实现,里面的功能包括了:

wsgi的环境变量 应答头部的处理 实现简单的HTTP服务器 简单的对程序端和服务器端校验函数

我们先看一个简单的代码实例,然后跟着例子去理解源码: app.py

#encoding:utf-8 # __author__ = 'donghao' # __time__ = 2019/3/29 14:17 def hello_world_app(environ, start_response): from io import StringIO stdout = StringIO() start_response("200 OK", [('Content-Type','text/html; charset=utf-8')]) return ['hello world'.encode('utf-8')]

server.py

from wsgiref.simple_server import make_server httpd = make_server('', 8000, hello_world_app) print("Serving on port 8000...") httpd.serve_forever() #浏览器 """ Content-Length: 20 Content-Type: text/html; charset=utf-8 Date: Fri, 29 Mar 2019 08:08:47 GMT Server: WSGIServer/0.2 CPython/3.6.4 """ #server终端 """ Serving on port 8000... 127.0.0.1 - - [29/Mar/2019 16:19:12] "GET / HTTP/1.1" 200 20 """

源码分析:

wsgiref |-- handlers.py # 核心代码,负责 wsgi 程序的处理 |-- headers.py # 头部处理的代码 |-- init.py # |-- simple_server.py # 简单的 wsgi HTTP 服务器实现 |-- util.py # 帮助函数 `-- validate.py # wsgi 格式检查和校验 主要的代码结构如下图所示:

simple_server.py 我们先看一下make_server是怎么启动一个wsgi服务器的:

def make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler): server = server_class((host, port), handler_class) server.set_app(app) return server

这个函数做的事情就是:监听在本地的端口上,接受来自客户端的请求,通过WSGIServer和WSGIRequestHandler处理后,把请求交给程序的的可调用对象app,然后返回app的结果给客户端。

这里有两个重要的类:WSGIServer和WSGIRequestHandler。下面分别看一下它们的代码和执行的功能。

WSGIServer

#WSGIServer class WSGIServer(HTTPServer): """BaseHTTPServer that implements the Python WSGI protocol""" application = None def server_bind(self): """Override server_bind to store the server name.""" HTTPServer.server_bind(self) self.setup_environ() def setup_environ(self): # Set up base environment env = self.base_environ = {} env['SERVER_NAME'] = self.server_name env['GATEWAY_INTERFACE'] = 'CGI/1.1' env['SERVER_PORT'] = str(self.server_port) env['REMOTE_HOST']='' env['CONTENT_LENGTH']='' env['SCRIPT_NAME'] = '' def get_app(self): return self.application def set_app(self,application): self.application = application

WSGIServer在原来的HTTPServer上面封装了一层,在原来的HTTPServer的基础上又额外做了下面的事情:

覆写原来的server_bind函数,添加初始化environ变量的动作 添加了处理满足wsgi的app函数:set_app和get_app

WSGIRequestHandler

# WSGIRequestHandler class WSGIRequestHandler(BaseHTTPRequestHandler): server_version = "WSGIServer/" + __version__ def get_environ(self): env = self.server.base_environ.copy() env['SERVER_PROTOCOL'] = self.request_version env['REQUEST_METHOD'] = self.command if '?' in self.path: path,query = self.path.split('?',1) else: path,query = self.path,'' env['PATH_INFO'] = urllib.unquote(path) env['QUERY_STRING'] = query host = self.address_string() if host != self.client_address[0]: env['REMOTE_HOST'] = host env['REMOTE_ADDR'] = self.client_address[0] if self.headers.typeheader is None: env['CONTENT_TYPE'] = self.headers.type else: env['CONTENT_TYPE'] = self.headers.typeheader length = self.headers.getheader('content-length') if length: env['CONTENT_LENGTH'] = length for h in self.headers.headers: k,v = h.split(':',1) k=k.replace('-','_').upper(); v=v.strip() if k in env: continue # skip content length, type,etc. if 'HTTP_'+k in env: env['HTTP_'+k] += ','+v # comma-separate multiple headers else: env['HTTP_'+k] = v return env def get_stderr(self): return sys.stderr def handle(self): """Handle a single HTTP request""" self.raw_requestline = self.rfile.readline() if not self.parse_request(): # An error code has been sent, just exit return handler = ServerHandler( self.rfile, self.wfile, self.get_stderr(), self.get_environ() ) handler.request_handler = self # backpointer for logging handler.run(self.server.get_app())

这个类从名字就能知道它的功能 - 处理客户端的HTTP请求,它也是在原来处理http请求的BaseHTTPRequestHandler类上添加了wsgi规范相关的内容。

get_environ:解析环境变量 handle:处理请求,把封装的环境变量交给ServerHandler,然后由ServerHandler调用wsgi app,ServerHandler类会在下面介绍。

handler.py 这个文件主要是wsgi server的处理过程,定义start_response,调用wsgi app,处理content-length等等。

一条HTTP请求的旅程 服务器端启动服务,等到客户端输入curl -i http://localhost:8000/命令,摁下回车键,看到终端上的输出,整个过程中,wsgi的服务器端发生了什么呢?

服务器程序创建socket,并监听在特定的端口,等待客户端的连接 客户端发送http请求 socket服务器读取请求的数据,交给http服务器 http server根据http的规范解析请求,然后把请求交给WSGIServer WSGIServer把客户端的信息存放在环境变量里,然后交给绑定的handler handler理请求 HTTPHandler解析请求,把方法,路径等放在environ,然后WSGIRequestHandler把服务器端的信息也放到environ里 WSGIRequestHandler调用绑定的wsgi ServerHandler,把上面包含了服务器信息,客户端信息,本次请求信息得environ传递过去 wsgi ServerHandler调用注册的wsgi app,把环境和start_response传递过去 wsgi app将响应头,状态,身体回传给wsgi处理程序 然后处理器逐层传递,最后把这些信息通过socket发送到客户端 客户端的程序接到应答,解析应答,并把结果打印出来 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2019032916561883.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMjM5NTIw,size_16,color_FFFFFF,t_70 =2000x800) 自己画的图,虽有点丑,回顾还是很有用。 wsgiref源码解析的更多相关文章 wsgiref 源码解析

Web Server Gateway Interface(wsgi),即Web服务器网关接口,是Web服务器软件和用Python编写的Web应用程序之间的标准接口. 想了解更多关于WSGI请前往: h ...

【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

jQuery2.x源码解析(缓存篇)

jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 缓存是jQuery中的又一核心设计,jQuery ...

Spring IoC源码解析——Bean的创建和初始化

Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

jQuery2.x源码解析(构建篇)

jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 笔者阅读了园友艾伦 Aaron的系列博客< ...

jQuery2.x源码解析(设计篇)

jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...

随机推荐 快速解决PL/SQL Developer过期问题(无需注册码等复杂操作)

第一步:在开始菜单中输入 :regedit  的指令,点击回车,进入注册表编辑器界面 第二步:在注册表里按HKEY_CURRENT_USER\Software\Allround Automations ...

Vue 制作简易计算器

...

babel简介

1.babel是什么 babel官网正中间一行黄色大字写着“babel is a javascript compiler”,翻译一下就是babel是一个javascript转译器.为什么会有babel ...

php获取指定日期,前一天、前一周、前一个月、前一年,后一天,后一周,前一个月,前一年

dump( date( 'Y-m-d', strtotime('2018-10-1 +1 day') ) ); dump( date( 'Y-m-d', strtotime('2018-10-1 +1 ...

centos7.6 ssh远程链接配置

1.firewall增加22端口号 增加方式有两种,直接编辑firewall的public.xml增加 vi /etc/firewalld/zones/public.xml 进入后按i健光标移动到zo ...

线程中的join方法

join方法的作用是同步线程. 1.不使用join方法:当设置多个线程时,在一般情况下(无守护线程,setDeamon=False),多个线程同时启动,主线程执行完,会等待其他子线程执行完,程序才会退 ...

vue-element 动态单选多选全选

实现效果如图 数据格式如下: pps: [{"code":"6","createTime":"2018-09-07 00:00:0 ...

PowerShell工作流学习-6-向脚本工作流添加检查点

关键点: a)检查点是工作流当前状态的快照,其中包括变量的当前值以及在该点生成的任何输出,这些信息保存在磁盘. b)检查点数据保存在托管工作流会话的计算机的硬盘上的用户配置文件中. c)当工作流通用参 ...

SVN服务端和客户端的安装与搭建

版权声明:本文为博主原创文章,转载请注明原文出处. https://blog.csdn.net/zzfenglin/article/details/50931462 SVN简介 SVN全名Subver ...

扁平化promise调用链(译)

这是对Flattened Promise Chains的翻译,水平有限请见谅^ ^. Promises对于解决复杂异步请求与响应问题堪称伟大.AngularJS提供了$q和$http来实现它:还有很多 ...



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3