bobdu.cc

Follow me on GitHub

利用Python启动一个最简单的Web服务器

usage: server.py [-h] [–cgi] [–bind ADDRESS] [port]

python -m http.server --cgi -b 0.0.0.0 61111

这条命令需要在Web资源存放目录下执行,并且Python脚本需要放在./cgi-bin/文件夹下


python内置的http包中的http.server模块

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--cgi', action='store_true',
                       help='Run as CGI Server')
    parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
                        help='Specify alternate bind address '
                             '[default: all interfaces]')
    parser.add_argument('port', action='store',
                        default=8000, type=int,
                        nargs='?',
                        help='Specify alternate port [default: 8000]')
    args = parser.parse_args()
    if args.cgi:
        handler_class = CGIHTTPRequestHandler
    else:
        handler_class = SimpleHTTPRequestHandler
    test(HandlerClass=handler_class, port=args.port, bind=args.bind)

当该模块直接被运行时, 读取启动命令的参数, 若有–cgi 则使用CGIHTTPRequestHandler处理请求 否则使用SimpleHTTPRequestHandler处理请求 调用test()函数


test()

def test(HandlerClass=BaseHTTPRequestHandler,
         ServerClass=HTTPServer, protocol="HTTP/1.0", port=8000, bind=""):
    """Test the HTTP request handler class.

    This runs an HTTP server on port 8000 (or the port argument).

    """
    server_address = (bind, port)

    HandlerClass.protocol_version = protocol
    with ServerClass(server_address, HandlerClass) as httpd:
        sa = httpd.socket.getsockname()
        serve_message = "Serving HTTP on {host} port {port} (http://{host}:{port}/) ..."
        print(serve_message.format(host=sa[0], port=sa[1]))
        try:
            httpd.serve_forever()
        except KeyboardInterrupt:
            print("\nKeyboard interrupt received, exiting.")
            sys.exit(0)

其中HTTPServer就是继承自socketserver.TCPServer 并重载了server_bind()方法

class HTTPServer(socketserver.TCPServer):

    allow_reuse_address = 1    # Seems to make sense in testing environment

    def server_bind(self):
        """Override server_bind to store the server name."""
        socketserver.TCPServer.server_bind(self)
        host, port = self.server_address[:2]
        self.server_name = socket.getfqdn(host)
        self.server_port = port

就是在创建一个TCP socker服务器端套接字,绑定到某个IP及端口进行监听

在实例化socketserver.TCPServer类时,需要提供一个socketserver.StreamRequestHandler类作为参数,在这个类中定义对客户端请求的处理方式


HTTPRequestHandler

BaseHTTPRequestHandler 继承自 socketserver.StreamRequestHandler

只有基本的Web服务器 除了获得客户端的请求外,没有其他处理

SimpleHTTPRequestHandler 继承自 BaseHTTPRequestHandler

以非常直接的形式实现了标准的 GET 和 HEAD 请求 已经可以完成一些简单的功能

CGIHTTPRequestHandler 继承自 SimpleHTTPRequestHandler

添加了对POST请求的支持 并且可以调用CGI脚本完成请求处理过程 也可以将生成的HTML脚本返回给客户端