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源码学习的更多相关文章

  1. Python库源码学习1:Flask之app.run

    先列出app.run()实现的功能,我们以debug=True的情况下进行分析. 1. web服务器,处理http请求 2. 当代码修改后,重启服务器 那么app.run()是如何实现这两个功能的呢? ...

  2. python源码学习(一)——python的总体架构

    python源码学习(一)——python的总体架构 学习环境: 系统:ubuntu 12.04 STLpython版本:2.7既然要学习python的源码,首先我们要在电脑上安装python并且下载 ...

  3. python 协程库gevent学习--gevent源码学习(二)

    在进行gevent源码学习一分析之后,我还对两个比较核心的问题抱有疑问: 1. gevent.Greenlet.join()以及他的list版本joinall()的原理和使用. 2. 关于在使用mon ...

  4. 『TensorFlow』SSD源码学习_其一:论文及开源项目文档介绍

    一.论文介绍 读论文系列:Object Detection ECCV2016 SSD 一句话概括:SSD就是关于类别的多尺度RPN网络 基本思路: 基础网络后接多层feature map 多层feat ...

  5. 《python解释器源码剖析》第0章--python的架构与编译python

    本系列是以陈儒先生的<python源码剖析>为学习素材,所记录的学习内容.不同的是陈儒先生的<python源码剖析>所剖析的是python2.5,本系列对应的是python3. ...

  6. [阿里DIN] 从论文源码学习 之 embedding层如何自动更新

    [阿里DIN] 从论文源码学习 之 embedding层如何自动更新 目录 [阿里DIN] 从论文源码学习 之 embedding层如何自动更新 0x00 摘要 0x01 DIN源码 1.1 问题 1 ...

  7. Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

    2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...

  8. jQuery源码学习感想

    还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...

  9. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

随机推荐

  1. 【容斥原理】CDOJ - 1544 - 当咸鱼也要按照基本法

    众所周知zhu是一个大厨,zhu一直有自己独特的咸鱼制作技巧. tang是一个咸鱼供应商,他告诉zhu在他那里面有NN条咸鱼(标号从1到N)可以被用来制作. 每条咸鱼都有一个咸鱼值KiKi,初始时所有 ...

  2. 【线段树】bzoj3038 上帝造题的七分钟2 / bzoj3211 花神游历各国

    暴力修改,记录一段是否全部为1或0,若全是了,则不再修改. 注意3211一定要判是否为0,否则会T得惨无人道. #include<cstdio> #include<cmath> ...

  3. Java多线程——AQS框架源码阅读

    AQS,全称AbstractQueuedSynchronizer,是Concurrent包锁的核心,没有AQS就没有Java的Concurrent包.它到底是个什么,我们来看看源码的第一段注解是怎么说 ...

  4. python内建datetime模块

    datetime 获取当前日期和时间 from datetime import datetime now = datetime.now() print(now) datetime转换为timestam ...

  5. javascript:使用代理绑定事件

    <ul id="box"> <li>1</li> <li>2</li> <li>3</li> & ...

  6. asp.mvc展示model

    1. ASP.Net MVC 3 Model 简介 通过一简单的事例一步一步的介绍2. ASP.Net MVC 3 Model 的一些验证 MVC 中 Model 主要负责维持数据状态,将数据从数据存 ...

  7. C# log4net打不出日志 (IIS项目)

    配置文件都配了,引用也引用了,调用也是对的,网上找博客也找不到,疯掉了. 后来腆着脸问了一个前辈,他告诉我的,添完就好了. 给项目的这个文件,添加这行代码: [assembly: log4net.Co ...

  8. Docker时间和宿主同步

    通过date命令查看时间 查看主机时间 [root@localhost ~]# date 2016年 07月 27日 星期三 22:42:44 CST 查看容器时间 root@b43340ecf5ef ...

  9. javascript中常见的函数封装 :判断是否是手机,判断是否是微信,获取url地址?后面的具体参数值,毫秒格式化时间,手机端px、rem尺寸转换等

    // 判断是否是手机function plat_is_mobile(){ var sUserAgent = navigator.userAgent.toLowerCase(); var bIsIpad ...

  10. golangWEB框架gin学习之获取get参数

    原文地址:http://www.niu12.com/article/40package main import ( "fmt" "github.com/gin-gonic ...