python SimpleHTTPServer源码学习
SimpleHTTPServer.SimpleHTTPRequestHandler继承了BaseHTTPServer.BaseHTTPRequestHandler。
源码中主要实现了BaseHTTPServer.BaseHTTPRequestHandler处理时需要调用的do_Head()和do_GET()函数。这类函数主要是在BaseHTTPRequestHandler在接受请求并判断请求头中的command之后调用的。
def handle_one_request(self):
... ...
mname = 'do_' + self.command
if not hasattr(self, mname):
self.send_error(501, "Unsupported method (%r)" % self.command)
return
method = getattr(self, mname)
method()
... ...
因此,在我们使用SimpleHTTPServer 对web请求处理时基本都需要调用这个method(),当然,其他异常情况除外。
SimpleHTTPServer.SimpleHTTPRequestHandler默认的处理是,如果在执行该脚本的当前目录含有 index.html或index.htm时,将把这个文件的html内容作为首页,如果不存在,则在界面显示当前目录下的文件夹内容,并内部将其设置html页面展现方式。
def list_directory(self, path):
"""Helper to produce a directory listing (absent index.html). Return value is either a file object, or None (indicating an
error). In either case, the headers are sent, making the
interface the same as for send_head(). """
try:
list = os.listdir(path)
except os.error:
self.send_error(404, "No permission to list directory")
return None
list.sort(key=lambda a: a.lower())
f = StringIO()
displaypath = cgi.escape(urllib.unquote(self.path))
f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
f.write("<hr>\n<ul>\n")
for name in list:
fullname = os.path.join(path, name)
displayname = linkname = name
# Append / for directories or @ for symbolic links
if os.path.isdir(fullname):
displayname = name + "/"
linkname = name + "/"
if os.path.islink(fullname):
displayname = name + "@"
# Note: a link to a directory displays with @ and links with /
f.write('<li><a href="%s">%s</a>\n'
% (urllib.quote(linkname), cgi.escape(displayname)))
f.write("</ul>\n<hr>\n</body>\n</html>\n")
length = f.tell()
f.seek(0)
self.send_response(200)
encoding = sys.getfilesystemencoding()
self.send_header("Content-type", "text/html; charset=%s" % encoding)
self.send_header("Content-Length", str(length))
self.end_headers()
return f
SimpleHTTPRequestHandler中list_directory()
其实对于socket的请求整理是在SocketServer.TCPServer中处理的,对web请求头的处理是在BaseHTTPServer.BaseHTTPRequestHandler中处理的,其对头的类型,版本等作了处理。而对于请求的回应则在子类SimpleHTTPServer.SimpleHTTPRequestHandler中处理。
那么,SimpleHTTPServer.SimpleHTTPRequestHandler是如何作出上述说明的请求的呢?
首先,Simple通过send_head()函数内部预先分析了请求的url路径,然后提取路径与当前目录路径组合得到请求的绝对路径地址,如果在该路径下存在index.html或index.htm文件则将这个文件内容打开并设置回馈头的内容,写入文件内容的长度和内容的类型,如果没有这个文件,则将获取当前目录下的内容,创建一个文件缓存写入一个html格式的内容,其中写明当前目录所具有的内容并设置超链接,使得用户点击时服务器能正确的回馈对应内容。
我们发现send_head()其实发送的请求头是根据请求内容进行设置的,也就是说在send_head()中,Simple已经把请求data准备好了,所以在send_head()之后只需要调用self.copyfile(f, self.wfile)将文件对象或缓存文件对象中的内容写入请求流对象中即可。
至于其他函数,都是为这些作准备的。
*值得注意的是,在读取本地文件回馈给客户端时要注意文件需要以rb的方式,即二进制方式去读,这样就避免文本流中换行了,也能正确的就算出流的长度(长度是作为回馈头的一部分反馈出去的)。
python SimpleHTTPServer源码学习的更多相关文章
- Python库源码学习1:Flask之app.run
先列出app.run()实现的功能,我们以debug=True的情况下进行分析. 1. web服务器,处理http请求 2. 当代码修改后,重启服务器 那么app.run()是如何实现这两个功能的呢? ...
- python源码学习(一)——python的总体架构
python源码学习(一)——python的总体架构 学习环境: 系统:ubuntu 12.04 STLpython版本:2.7既然要学习python的源码,首先我们要在电脑上安装python并且下载 ...
- python 协程库gevent学习--gevent源码学习(二)
在进行gevent源码学习一分析之后,我还对两个比较核心的问题抱有疑问: 1. gevent.Greenlet.join()以及他的list版本joinall()的原理和使用. 2. 关于在使用mon ...
- 『TensorFlow』SSD源码学习_其一:论文及开源项目文档介绍
一.论文介绍 读论文系列:Object Detection ECCV2016 SSD 一句话概括:SSD就是关于类别的多尺度RPN网络 基本思路: 基础网络后接多层feature map 多层feat ...
- 《python解释器源码剖析》第0章--python的架构与编译python
本系列是以陈儒先生的<python源码剖析>为学习素材,所记录的学习内容.不同的是陈儒先生的<python源码剖析>所剖析的是python2.5,本系列对应的是python3. ...
- [阿里DIN] 从论文源码学习 之 embedding层如何自动更新
[阿里DIN] 从论文源码学习 之 embedding层如何自动更新 目录 [阿里DIN] 从论文源码学习 之 embedding层如何自动更新 0x00 摘要 0x01 DIN源码 1.1 问题 1 ...
- Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结
2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...
- jQuery源码学习感想
还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...
- MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
随机推荐
- python3 开发面试题(常用模块以及第三方库)6.5
""" 1. os和sys都是干什么的? 2. 你工作中都用过哪些内置模块? 3. 有没有用过functools模块? """ #sys模块 ...
- Java高级架构师(一)第11节:Mybatis的分页实现
- JavaScript学习系列之执行上下文与变量对象篇
一个热爱技术的菜鸟...用点滴的积累铸就明日的达人 正文 在上一篇文章中讲解了JavaScript内存模型,其中有提到执行上下文与变量对象的概念.对于JavaScript开发者来说,理解执行上下文与变 ...
- iOS开发经验——点击屏幕空白处退出键盘
一种比较简单的点击屏幕空白处退出键盘的方法: 在ViewController中加入如下代码: 1: -(void)touchesBegan:(NSSet *)touches withEve ...
- iOS 简单易用的二维码扫描及生成二维码三方控件LFQRCode,可灵活自定义UI
一.扫码 扫描的控件是一个view,使用者只需贴在自己的控制器内即可.其他UI用户可在自己控制器随便添加.代码如下 - (void)viewDidLoad { [super viewDidLoad]; ...
- iOS:地图笔记
地图笔记 01. CLLocation -------------------------------------------------------- CLLocationManager 定位管理者 ...
- Zabbix的SNMPTrap监控配置
SNMPTrap监控主要用于设备发生故障时的主动通知的监控.以下简单记录下Zabbix的SNMPTrap的配置方法. 一.SNMPTrap监控的处理流程说明 1.监控对象发送SNMPTrap信息到sn ...
- RDD编程 上(Spark自学三)
弹性分布式数据集(简称RDD)是Spark对数据的核心抽象.RDD其实就是分布式的元素集合.在Spark中,对数据的操作不外乎创建RDD.转化已有RDD以及调用RDD操作进行求值.而在这一切背后,Sp ...
- es6 中的 模板字符串
Template literals are string literals allowing embedded expressions. You can use multi-line strings ...
- 各版本JDK1.5-1.8新特性
概述 一jdk15新特性 泛型 foreach 自动拆箱装箱 枚举 静态导入Static import 元数据Metadata 线程池 Java Generics 二jdk16新特性 Desktop类 ...