美文网首页实验报告
Python 《Python 实现简单 Web 服务器》实验报告

Python 《Python 实现简单 Web 服务器》实验报告

作者: Yohann丶blog | 来源:发表于2020-08-13 14:43 被阅读0次
WechatIMG62.jpeg

环境

  • macOS 10.14.6

  • Python 3.7.7

  • httpie

httpie 是一个命令行 HTTP 客户端。

安装httpie

  • 安装
$ brew install httpie

这里使用 homebrew 安装 httpie。

  • 查看版本
$ http --version
2.2.0

代码

#-*- coding:utf-8 -*-

import sys, os, urllib, subprocess
import urllib.parse
import urllib.request
from http.server import BaseHTTPRequestHandler,HTTPServer
#-------------------------------------------------------------------------------

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

#-------------------------------------------------------------------------------

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.handle_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 case_no_file(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_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 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_directory_index_file(base_case):
    '''在根路径下返回主页文件'''

    def test(self, handler):
        return os.path.isdir(handler.full_path) and \
               os.path.isfile(self.index_path(handler))

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

#-------------------------------------------------------------------------------

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 RequestHandler(BaseHTTPRequestHandler):
    '''
    请求路径合法则返回相应处理
    否则返回错误页面
    '''

    Cases = [case_no_file(),
             case_cgi_file(),
             case_existing_file(),
             case_directory_index_file(),
             case_always_fail()]

    # 错误页面模板
    Error_Page = """\
        <html>
        <body>
        <h1>Error accessing {path}</h1>
        <p>{msg}</p>
        </body>
        </html>
        """

    # 处理get请求
    def do_GET(self):
        try:

            # 得到完整的请求路径
            self.full_path = os.getcwd() + self.path
            # 遍历所有的情况并处理
            for case in self.Cases:
                if case.test(self):
                    case.act(self)
                    break

        # 处理异常
        except Exception as msg:
            self.handle_error(msg)

    # 处理post请求
    def do_POST(self):
        datas = self.rfile.read(int(self.headers['content-length']))
        self.send_content(datas)

    # 处理异常
    def handle_error(self, msg):
        content = self.Error_Page.format(path=self.path, msg=msg)
        self.send_content(content.encode("utf-8"), 404)

    # 发送数据到客户端
    def send_content(self, content, status=200):
        self.send_response(status)
        self.send_header("Content-type", "text/html")
        self.send_header("Content-Length", str(len(content)))
        self.end_headers()
        self.wfile.write(content)

#-------------------------------------------------------------------------------

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

创建 server.py,内容如上。

运行

  • 启动服务器
$ python server.py &

&表示将这个任务放到后台去执行。

  • get 请求
$ http 0.0.0.0:8080/home.html
HTTP/1.0 404 Not Found
Content-Length: 152
Content-type: text/html
Date: Thu, 13 Aug 2020 06:22:48 GMT
Server: BaseHTTP/0.6 Python/3.7.7

<html>
        <body>
        <h1>Error accessing /home.html</h1>
        <p>'/home.html' not found</p>
        </body>
        </html>
  • post 请求
$ http 0.0.0.0:8080 hello=world
HTTP/1.0 200 OK
Content-Length: 18
Content-type: text/html
Date: Thu, 13 Aug 2020 06:07:27 GMT
Server: BaseHTTP/0.6 Python/3.7.7

{
    "hello": "world"
}

相关文章

网友评论

    本文标题:Python 《Python 实现简单 Web 服务器》实验报告

    本文链接:https://www.haomeiwen.com/subject/njgbdktx.html