1、实现简单的web服务器

1、web-server文件下有index.html,plain.html,server.py,time.py文件

from http.server import BaseHTTPRequestHandler, HTTPServer
import subprocess, os


class base_case(object):
    '''条件处理基类'''
    def handle_file(self, handler, full_path):
        try:
            with open(full_path, 'rb') as reader:
                content = reader.read()
            handler.send_content(content)
        except IOError as msg:
            msg = "'{0} cannot be read: {1}'".format(full_path, msg)
            handler.send_error(msg)

    def index_path(self, handler):
        return os.path.join(handler.full_path, 'index.html')

    # 要求子类必须实现的接口
    def test(self, handler):
        assert False, 'Not implemented'

    def act(self, handler):
        assert False, 'Not implemented'

class ServerException(Exception):
    '''服务器内部错误'''
    pass

class case_directory_index_file(base_case):
    '''条件处理类'''
    # 判断目标路径是否是目录&&目录下是否有index.html
    def test(self, handler):
        return os.path.isdir(handler.full_path) and os.path.isfile(self.index_path(handler))

    # 响应index.html的内容
    def act(self, handler):
        self.handle_file(handler, self.index_path(handler))

class case_no_flie(base_case):
    '''该路径不存在'''
    def test(self, handler):
        return not os.path.exists(handler.full_path)

    def act(self, handler):
        raise ServerException("'{0}' not found".format(handler.path))

class case_existing_file(base_case):
    '''该路径是文件'''
    def test(self, handler):
        return os.path.isfile(handler.full_path)

    def act(self, handler):
        self.handle_file(handler, handler.full_path)

class case_always_fail(base_case):
    '''所有情况都不符合时的默认处理类'''
    def test(self, handler):
        return True

    def act(self, handler):
        raise ServerException("Unknown object '{0}'".format(handler.path))

class case_cgi_file(base_case):
    '''脚本文件处理'''
    def run_cgi(self, handler):
        data = subprocess.check_output(['python3', handler.full_path],shell=False)
        handler.send_content(data)

    def test(self, handler):
        return os.path.isfile(handler.full_path) and handler.full_path.endswith('.py')

    def act(self, handler):
        # 运行脚本文件
        self.run_cgi(handler)

class RequestHandler(BaseHTTPRequestHandler):
    '''处理请求并返回页面'''
    # 错误页面模板
    Error_Page = """\
        <html>
        <body>
        <h1>Error accessing {path}</h1>
        <p>{msg}</p>
        </body>
        </html>
        """

    # 所有可能的情况
    # 注意这里的顺序, 需要先判断是否是需要执行的脚本文件,再判断是否是普通文件
    Cases = [case_no_flie(), case_cgi_file(), case_existing_file(), case_directory_index_file(), case_always_fail()]
    # 处理一个get请求
    def do_GET(self):
        try:
            # 文件完整路径
            self.full_path = os.getcwd() + self.path

            # 遍历所有可能情况
            for case in self.Cases:
                if case.test(self):
                    # 调用相应的act函数
                    case.act(self)
                    break
        # 处理异常
        except Exception as msg:
            self.handle_error(msg)

    # 返回内容给客户端
    def send_content(self, page, status=200):
        self.send_response(status)
        self.send_header('Content-Type', 'text/html')
        self.send_header('Content-Length', str(len(page)))
        self.end_headers()
        self.wfile.write(page)

    # 错误处理函数
    def handle_error(self, msg):
        content = self.Error_Page.format(path=self.path, msg=msg)
        self.send_content(content.encode('utf-8'), 404)



if __name__ == '__main__':
    serverAddress = ('127.0.0.1', 8080)
    server = HTTPServer(serverAddress, RequestHandler)
    server.serve_forever()

 

posted @ 2018-06-27 14:09  起航追梦人  阅读(182)  评论(0编辑  收藏  举报