改善Python自带的HTTP服务器SimpleHTTPServer

2014-05-07

笔者使用的python版本是2.7.6。

陈皓在非常简单的Python HTTP服务介绍了python自带的针对静态网站的http服务器,例如要以/home/www为http server的DocumentRoot,可以:

cd /home/www
python -m SimpleHTTPServer

之后在浏览器中访问http://127.0.0.1:8000即可。

这种方法在我的Linux Mint下运行正常,也可以正确的处理中文路径。

但是在windows下遇到中文路径时候就出问题了,可能会显示404,例如本站当前使用的是静态博客系统hexo,我

cd hexo\public
python -m SimpleHTTPServer

然后访问 http://127.0.0.1:8000/2014/04/27/代码高亮之Prism/,这个路径是确实存在的,但是却出现404错误:

404错误

有时候也会遇到列举目录内容的页面中的中文出现乱码的情况。

本文就试图解决这些情况。

分析问题


关于404

使用firebug分析访问http://127.0.0.1:8000/2014/04/27/代码高亮之Prism/时出现了什么情况,

首先查看到的请求头中的第一行内容如下:

GET /2014/04/27/%E4%BB%A3%E7%A0%81%E9%AB%98%E4%BA%AE%E4%B9%8BPrism/

python -m SimpleHTTPServer运行时会简要的显示部分工作过程
python server收到的请求如下以及发出的响应如下:

127.0.0.1 - - [07/May/2014 14:19:51] "GET /2014/04/27/%E4%BB%A3%E7%A0%81%E9%AB%98%E4%BA%AE%E4%B9%8BPrism/ HTTP/1.1" 404 -

客户端发送的请求路径和服务是相同的。本地文件系统中,2014/04/27/代码高亮之Prism/目录下也确实存在index.html。

代码高亮之Prism使用utf8进行urlencode的结果也是%E4%BB%A3%E7%A0%81%E9%AB%98%E4%BA%AE%E4%B9%8BPrism。 这说明SimpleHTTPServer没有正确将utf8编码的路径与windows系统下的相应文件对应起来。

也就是SimpleHTTPServer通过客户端请求的信息去打开本地的静态文件时,并没有正确的打开。如果相应的路径又确实存在的话,那么可能是SimpleHTTPServer直接

open('代码高亮之Prism/index.html')

,而非

open('代码高亮之Prism/index.html'.decode('utf-8'))

列举目录内容时候出现了什么情况

浏览器访问http://127.0.0.1:8000/2014/04/27/,结果如下:
正常显示,但背后隐藏着问题

首先使用firebug查看http响应头,

HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.7.6
Date: Wed, 07 May 2014 06:38:22 GMT
Content-Type: text/html; charset=mbcs
Content-Length: 272

其中比较奇怪的是charset指定的值是mbcs。(关于mbcs,请参考支持多字节字符集,其来源于python的SimpleHTTPServer模块,具体请查看源码,源码位置会在下文中提及。)

然后查看html源码:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Directory listing for /2014/04/27/</title>
</head>
<body>
<h2>Directory listing for /2014/04/27/</h2>
<hr>
<ul>
<li>
<a href="%B4%FA%C2%EB%B8%DF%C1%C1%D6%AEPrism/">代码高亮之Prism/</a>
</li>
</ul>
<hr>
</body>
</html>

首先上面的源码中并未指定

<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">

或者类似的内容。

另外,代码高亮之Prism的url编码明显和之前的不一样。

%B4%FA%C2%EB%B8%DF%C1%C1%D6%AEPrism

需要使用GB2312进行解码;

%E4%BB%A3%E7%A0%81%E9%AB%98%E4%BA%AE%E4%B9%8BPrism

需要使用UTF8解码,两者的解码结果都是代码高亮之Prism

分析SimpleHTTPServer


命令python -m SimpleHTTPServer中参数-m在文档中解释如下:

-m mod : run library module as a script (terminates option list)

也就是说。SimpleHTTPServer其实是一个模块。

以windows为例子,进入python安装路径,进入Lib目录,可以找到SimpleHTTPServer.py,在该文件最后可以找到以下内容:

def test(HandlerClass = SimpleHTTPRequestHandler,
         ServerClass = BaseHTTPServer.HTTPServer):
    BaseHTTPServer.test(HandlerClass, ServerClass)
if __name__ == '__main__':
    test()

这就是python -m SimpleHTTPServer能够运行的原因。

SimpleHTTPServer中的类 SimpleHTTPRequestHandler是核心内容,内容较简单,此处不做分析。

改善SimpleHTTPServer


笔者对python自带的SimpleHTTPServer略作修改,使其能在linux和windows正常工作,代码见下面。如果有读者要用到它,建议将其保存为SimpleHTTPServer2.py并放到目录Lib中,使用

python -m SimpleHTTPServer2

运行即可。 另外,若是需要改变监听端口、让SimpleHTTPServer/SimpleHTTPServer2只服务于本地环境,请参考非常简单的Python HTTP服务

地址: https://github.com/letiantian/SimpleHTTPServer2

( 完 )