这是一个专题 记录学习python标准库的笔记及心得

简单http服务 SimpleHTTPServer

使用 python -m SimpleHTTPServer 默认启动8000端口

源码:

  1. """Simple HTTP Server.
  2. This module builds on BaseHTTPServer by implementing the standard GET
  3. and HEAD requests in a fairly straightforward manner.
  4. """
  5. __version__ = "0.6"
  6. __all__ = ["SimpleHTTPRequestHandler"]
  7. import os
  8. import posixpath
  9. import BaseHTTPServer
  10. import urllib
  11. import urlparse
  12. import cgi
  13. import sys
  14. import shutil
  15. import mimetypes
  16. try:
  17. from cStringIO import StringIO
  18. except ImportError:
  19. from StringIO import StringIO
  20. class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  21. """Simple HTTP request handler with GET and HEAD commands.
  22. This serves files from the current directory and any of its
  23. subdirectories. The MIME type for files is determined by
  24. calling the .guess_type() method.
  25. The GET and HEAD requests are identical except that the HEAD
  26. request omits the actual contents of the file.
  27. """
  28. server_version = "SimpleHTTP/" + __version__
  29. def do_GET(self):
  30. """Serve a GET request."""
  31. f = self.send_head()
  32. if f:
  33. try:
  34. self.copyfile(f, self.wfile)
  35. finally:
  36. f.close()
  37. def do_HEAD(self):
  38. """Serve a HEAD request."""
  39. f = self.send_head()
  40. if f:
  41. f.close()
  42. def send_head(self):
  43. """Common code for GET and HEAD commands.
  44. This sends the response code and MIME headers.
  45. Return value is either a file object (which has to be copied
  46. to the outputfile by the caller unless the command was HEAD,
  47. and must be closed by the caller under all circumstances), or
  48. None, in which case the caller has nothing further to do.
  49. """
  50. path = self.translate_path(self.path)
  51. f = None
  52. if os.path.isdir(path):
  53. parts = urlparse.urlsplit(self.path)
  54. if not parts.path.endswith('/'):
  55. # redirect browser - doing basically what apache does
  56. self.send_response(301)
  57. new_parts = (parts[0], parts[1], parts[2] + '/',
  58. parts[3], parts[4])
  59. new_url = urlparse.urlunsplit(new_parts)
  60. self.send_header("Location", new_url)
  61. self.end_headers()
  62. return None
  63. for index in "index.html", "index.htm":
  64. index = os.path.join(path, index)
  65. if os.path.exists(index):
  66. path = index
  67. break
  68. else:
  69. return self.list_directory(path)
  70. ctype = self.guess_type(path)
  71. try:
  72. # Always read in binary mode. Opening files in text mode may cause
  73. # newline translations, making the actual size of the content
  74. # transmitted *less* than the content-length!
  75. f = open(path, 'rb')
  76. except IOError:
  77. self.send_error(404, "File not found")
  78. return None
  79. try:
  80. self.send_response(200)
  81. self.send_header("Content-type", ctype)
  82. fs = os.fstat(f.fileno())
  83. self.send_header("Content-Length", str(fs[6]))
  84. self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
  85. self.end_headers()
  86. return f
  87. except:
  88. f.close()
  89. raise
  90. def list_directory(self, path):
  91. """Helper to produce a directory listing (absent index.html).
  92. Return value is either a file object, or None (indicating an
  93. error). In either case, the headers are sent, making the
  94. interface the same as for send_head().
  95. """
  96. try:
  97. list = os.listdir(path)
  98. except os.error:
  99. self.send_error(404, "No permission to list directory")
  100. return None
  101. list.sort(key=lambda a: a.lower())
  102. f = StringIO()
  103. displaypath = cgi.escape(urllib.unquote(self.path))
  104. f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
  105. f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
  106. f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
  107. f.write("<hr>\n<ul>\n")
  108. for name in list:
  109. fullname = os.path.join(path, name)
  110. displayname = linkname = name
  111. # Append / for directories or @ for symbolic links
  112. if os.path.isdir(fullname):
  113. displayname = name + "/"
  114. linkname = name + "/"
  115. if os.path.islink(fullname):
  116. displayname = name + "@"
  117. # Note: a link to a directory displays with @ and links with /
  118. f.write('<li><a href="%s">%s</a>\n'
  119. % (urllib.quote(linkname), cgi.escape(displayname)))
  120. f.write("</ul>\n<hr>\n</body>\n</html>\n")
  121. length = f.tell()
  122. f.seek(0)
  123. self.send_response(200)
  124. encoding = sys.getfilesystemencoding()
  125. self.send_header("Content-type", "text/html; charset=%s" % encoding)
  126. self.send_header("Content-Length", str(length))
  127. self.end_headers()
  128. return f
  129. def translate_path(self, path):
  130. """Translate a /-separated PATH to the local filename syntax.
  131. Components that mean special things to the local file system
  132. (e.g. drive or directory names) are ignored. (XXX They should
  133. probably be diagnosed.)
  134. """
  135. # abandon query parameters
  136. path = path.split('?',1)[0]
  137. path = path.split('#',1)[0]
  138. # Don't forget explicit trailing slash when normalizing. Issue17324
  139. trailing_slash = path.rstrip().endswith('/')
  140. path = posixpath.normpath(urllib.unquote(path))
  141. words = path.split('/')
  142. words = filter(None, words)
  143. path = os.getcwd()
  144. for word in words:
  145. if os.path.dirname(word) or word in (os.curdir, os.pardir):
  146. # Ignore components that are not a simple file/directory name
  147. continue
  148. path = os.path.join(path, word)
  149. if trailing_slash:
  150. path += '/'
  151. return path
  152. def copyfile(self, source, outputfile):
  153. """Copy all data between two file objects.
  154. The SOURCE argument is a file object open for reading
  155. (or anything with a read() method) and the DESTINATION
  156. argument is a file object open for writing (or
  157. anything with a write() method).
  158. The only reason for overriding this would be to change
  159. the block size or perhaps to replace newlines by CRLF
  160. -- note however that this the default server uses this
  161. to copy binary data as well.
  162. """
  163. shutil.copyfileobj(source, outputfile)
  164. def guess_type(self, path):
  165. """Guess the type of a file.
  166. Argument is a PATH (a filename).
  167. Return value is a string of the form type/subtype,
  168. usable for a MIME Content-type header.
  169. The default implementation looks the file's extension
  170. up in the table self.extensions_map, using application/octet-stream
  171. as a default; however it would be permissible (if
  172. slow) to look inside the data to make a better guess.
  173. """
  174. base, ext = posixpath.splitext(path)
  175. if ext in self.extensions_map:
  176. return self.extensions_map[ext]
  177. ext = ext.lower()
  178. if ext in self.extensions_map:
  179. return self.extensions_map[ext]
  180. else:
  181. return self.extensions_map['']
  182. if not mimetypes.inited:
  183. mimetypes.init() # try to read system mime.types
  184. extensions_map = mimetypes.types_map.copy()
  185. extensions_map.update({
  186. '': 'application/octet-stream', # Default
  187. '.py': 'text/plain',
  188. '.c': 'text/plain',
  189. '.h': 'text/plain',
  190. })
  191. def test(HandlerClass = SimpleHTTPRequestHandler,
  192. ServerClass = BaseHTTPServer.HTTPServer):
  193. BaseHTTPServer.test(HandlerClass, ServerClass)
  194. if __name__ == '__main__':
  195. test()

接收GET,HEAD请求

先判断是否是目录,目录不加/会重定向,默认显示目录下的index.html/index.htm文件,如果没有上述文件将目录下文件列表显示

copyfile函数调用shutil基本库,以后再介绍

利用MIME进行文件类型判断

python标准库学习-SimpleHTTPServer的更多相关文章

  1. Python标准库学习之zipfile模块

    ZipFile模块里有两个非常重要的class, 分别是 ZipFile和ZipInfo. ZipFile是主要的类,用来创建和读取zip文件,而ZipInfo是存储的zip文件的每个文件的信息的. ...

  2. python标准库学习-ftplib

    源码: """An FTP client class and some helper functions. Based on RFC 959: File Transfer ...

  3. 【python标准库学习】thread,threading(一)多线程的介绍和使用

    在单个程序中我们经常用多线程来处理不同的工作,尤其是有的工作需要等,那么我们会新建一个线程去等然后执行某些操作,当做完事后线程退出被回收.当一个程序运行时,就会有一个进程被系统所创建,同时也会有一个线 ...

  4. python标准库00 学习准备

    Python标准库----走马观花 python有一套很有用的标准库.标准库会随着python解释器一起安装在你的电脑上的.它是python的一个组成部分.这些标准库是python为你准备的利器,可以 ...

  5. Python标准库的学习准备

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Python标准库是Python强大的动力所在,我们已经在前文中有所介绍.由于标准 ...

  6. Python 标准库一览(Python进阶学习)

    转自:http://blog.csdn.net/jurbo/article/details/52334345 写这个的起因是,还是因为在做Python challenge的时候,有的时候想解决问题,连 ...

  7. python第六天 函数 python标准库实例大全

    今天学习第一模块的最后一课课程--函数: python的第一个函数: 1 def func1(): 2 print('第一个函数') 3 return 0 4 func1() 1 同时返回多种类型时, ...

  8. Python标准库07 信号 (signal包,部分os包)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在了解了Linux的信号基础之后,Python标准库中的signal包就很容易学习 ...

  9. Python标准库——走马观花

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Python有一套很有用的标准库(standard library).标准库会随着 ...

随机推荐

  1. xcode 运行 lua版本崩溃 解决方案

    问题描述:运行到LuaStack::init() 崩溃 原因: luajit不支持arm64 解决方案:编译luajit64位静态库 a.可以直接下载别人编译好的库,然后直接覆盖cocos2d\ext ...

  2. 再谈iOS 7的手势滑动返回功能

    本文转载至 http://blog.csdn.net/jasonblog/article/details/28282147  之前随手写过一篇<使用UIScreenEdgePanGestureR ...

  3. $().each() 与 $.each()区别,以及 jquery ajax 应用

    在jquery 中我们可以选择$().each() 与 $.each() 进行迭代对象和数组 $(items).each(function(){ //item })   , 而后者则 $.each(i ...

  4. 【BZOJ4597】[Shoi2016]随机序列 线段树

    [BZOJ4597][Shoi2016]随机序列 Description 你的面前有N个数排成一行.分别为A1, A2, … , An.你打算在每相邻的两个 Ai和 Ai+1 间都插入一个加号或者减号 ...

  5. 史上最易懂的大数据 OTO

    史上最易懂的大数据 OTO http://network.51cto.com/art/201503/467068.htm 终于有人把O2O.C2C.B2B.B2C的区别讲透了 http://tech. ...

  6. 并发编程6 锁&进程&队列

    1.进程的其他方法 2.验证进程空间隔离和守护进程 3.孤儿进程和僵尸进程 4.锁 for循环加join数据共享 5.进程队列的简单应用 6.通过队列实现进程间的通信 7.生产者消费者模型及Queue ...

  7. python将图片转base64,前端显示

    https://blog.csdn.net/u013055678/article/details/71406746 <img src='xxxxxxx'> 跟这样的效果是一样的吧?     ...

  8. 关于jQuery中nth-child和nth-of-type的详解

    首先贴出来HTML的代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  9. redis中默认有多少个哈希槽?

    Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余 ...

  10. JSONObject和JSONArray 以及Mybatis传入Map类型参数

    import org.json.JSONArray;import org.json.JSONObject; 将字符串转化为JSONArray   JSONArray  jsonArray = new ...