SimpleHTTPServer的改造

起因

最近要写一个工具给商务部门的人使用,而我又不知道用Python写界面,于是想到了使用HTML
页面来做界面的IDEAL,但是我又不想自己的工具以来太多的三方库,那就使用SimpleHTTPServer
吧.

开始使用

SimpleHTTPServer的典型使用方式为:

httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', port), SimpleHTTPServer.SimpleHTTPRequestHandler)
sa = httpd.socket.getsockname()
httpd.serve_forever()

问题是SimpleHTTPRequestHandler只是用于静态页面,可以看它的源代码中是怎么处理的:

    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中的文件名称, 并读取本地对应的文件并返回

函数copyfile的功能就是将文件内容写入到网络通道.

现在我想用SimpleHTTPServer实现生成动态网页的功能,那该怎么办呢?

改造

看了源代码,最简单的解决方式就是继承SimpleHTTPRequestHandler并重写do_GET方法,然后在这里加上自己的处理逻辑

比如我的目标是能够让Web服务器在收到process.html?param=value这个请求时能够根据value
的值进行动态处理,修改后的代码如下

    def do_GET(self):
        if self.path.startswith('/process.html'):
            try:
                data = self.process_request()
                self.gen_file(data)
            except Exception, e:
                self.gen_file(e)
            f = self.send_head_1('result.html')
        else:
            f = self.send_head()

process_request():根据请求数据生成动态内容

gen_file():根据动态内容生成本地文件

send_head_1():读取指定的文件并返回

这里比较trick的就是由动态数据生成静态页面的过程:

  • 预先准备了一个模板文件, 其中的动态内容用特殊字符串标记
  • 生成动态内容后,读取模板文件,将特殊字符串标记替换为动态内容
  • 将替换后的内容保存到result.html中,并交由handler去读取内容
  • 后续的操作不变

总结

至此,一个简单的Handler就改造完毕, 它可以动态处理指定URI的GET请求, 或者直接读取
本地的文件返回给用户,基本上满足我这个工具的使用场景了.

但是从工程上来讲,这个解决方案是快速却又粗糙的:

  • 每次都需要读取模板文件,并没有将它缓存起来
  • 动态数据生成后,没必要再创建一个临时的result.html文件,然后去读取,直接将生成的内容
    写到管道中就行了.
  • 路由方案选择的是前缀匹配,而且都是写死的,并不能动态配置