Python运行环境:Ubuntu Ubuntu 18.04.1 LTS
本文仅用于记录学习和分析Python的过程,Python还有很多搭建web服务器的框架本文都不涉及。
执行命令:
$ python -m SimpleHTTPServer
//如果不指定端口,默认使用8000
然后在浏览器上输入:
http://localhost:8000/
//把localhost改成Linux主机ip
网页上显示出这个,那个A_File是我在Linux下运行Python文件里面的一个文件。
什么,就这么简单?好吧,作为一个Linux C程序员,不得不说,我得研究一下源码。
最基本的理解是,有网页就得有html文件,而且很显而易见的是,这个网页看上去是调整过格式的。
一开始想到就是在我的Linux环境里是有一个这样的html文件存在的,在使用SimpleHTTPServer模块时会找到它,并且推给前端。然后就在Python安装路径和系统里找这个文件,最后都把以前玩过的Apache和Tomcat里面的html都翻出来了也没对上号。。。
先考虑两点:
1. 打开网页时HTTP Server会有这样的信息:“GET / HTTP/1.1” 200 -。说明打开网页的时候执行的是GET请求(这个好像是理所当然的)。
2. 从浏览器上查看网页源码:
<html>
<title>Directory listing for /title>
<body>
<h2>Directory listing for /h2>
<hr>
<ul>
<li><a href="A_File">A_Filea>
ul>
<hr>
body>
html>
接下来从源码的角度分析一下:
在我的Linux系统中找到SimpleHTTPServer模块源码(感兴趣的源码自行查找),查看do_GET() 方法:
def do_GET(self):
"""Serve a GET request."""
f = self.send_head()
if f:
try:
self.copyfile(f, self.wfile)
finally:
f.close()
这么一看应该是要看一下send_head() 方法做了什么,里面有这样一段代码:
path = self.translate_path(self.path)
f = None
if os.path.isdir(path):
parts = urlparse.urlsplit(self.path)
if not parts.path.endswith('/'):
# redirect browser - doing basically what apache does
self.send_response(301)
new_parts = (parts[0], parts[1], parts[2] + '/',
parts[3], parts[4])
new_url = urlparse.urlunsplit(new_parts)
self.send_header("Location", new_url)
self.end_headers()
return None
for index in "index.html", "index.htm":
index = os.path.join(path, index)
if os.path.exists(index):
path = index
break
else:
return self.list_directory(path)
主要看一下for循环的作用,实际上是在当前路径下查找index.html, index.htm 如果没找到就return到 list_directory() 方法,紧接着就在list_directory() 方法里看到这样的代码:
f.write('')
f.write("\nDirectory listing for %s \n" % displaypath)
f.write("\nDirectory listing for %s
\n" % displaypath)
f.write("
\n\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('%s\n'
% (urllib.quote(linkname), cgi.escape(displayname)))
f.write("\n
\n\n\n")
很显然,这个段代码刚好对应到了上面贴的网页源码。现在真相大白了,在打开网页时do_GET() 方法会调用 list_directory() 创建一个html出来给前端显示。
虽然从代码的逻辑上分析完了,但是总觉得怪怪的,还是要自己跑一下代码才放心啊。
使用Python的好处就是可以方便的进行验证,这一点就比C方便的多。
首先把SimpleHTTPServer.py从源码路径里copy出来放到与A_File同一路径下,然后执行命令:
$ python SimpleHTTPServer.py
然后用服务器ip打开网页会看到:
网页可以正常打开,显示的也正是预期的结果,说明刚刚的操作是正确的。
这也正是用Python的优势所在,这个源码文件其实是需要BaseHTTPServer 等模块支持的,但是我并没有把这个模块copy过来。当然也是因为在Linux环境下安装Python的时候就已经配置好环境变量了。当然也可以类比Shell。
根据上面的分析,如果再当前路径下有html文件会怎么样呢?
创建一个index.html文件,里面加上一句"Hello World!",然后启动脚本在打开网页会显示如下:
(万年的Hello World???)
这说明之前对那个for 循环部分的代码分析是没错的。同样的可以把list_directory() 方法里面的StringIO 打印出来也会对上面的介绍进行验证。
至于在GET请求时 “GET / HTTP/1.1” 200 - 这个信息打印是怎么打印出来的呢,可以把BaseHTTPServer 模块源码copy过来做一下验证,里面有个log_message() 方法,具体代码逻辑就不在这里分析了。
也就是说,所有的现象只要仔细分析一下源码都能找到根源。
为什么要用Python搭建,因为如果单纯的想要从服务器上下载文件,用Python 的SimpleHTTPServer 模块搭建一个服务器要比搭建ftp或者是tftp简单的多。
但是这个单纯的执行一下 命令python -m SimpleHTTPServer,只能实现文件的下载功能,如果想要实现文件上传功能可以参考:https://github.com/tualatrix/tools/blob/master/SimpleHTTPServerWithUpload.py 这里面实现了POST请求功能。