python 搭建web服务器

使用 httpie 在命令行进行测试


1、最基本的:

# _*_coding :utf-8 _*_
import httpie
from http.server import BaseHTTPRequestHandler,HTTPServer

class RequestHandler(BaseHTTPRequestHandler):
    '''处理请求并返回页面'''
    # 页面模板
    Page = '''\
        <html>
        <body>
        <p>Hello, web!</p>
        </body>
        </html>
    '''
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type","text/html")
        self.send_header("Content-length",str(len(self.Page))) #字符串类型
        self.end_headers()
        self.wfile.write(self.Page.encode())


if __name__ == '__main__':
    print("server start...")
    serverAddr = ('',9999) #链接不上可能是端口号被占用 换个试试
    server = HTTPServer(serverAddr,RequestHandler)
    server.serve_forever()


2、封装创建page,发送报文的方法

# _*_coding :utf-8 _*_
import httpie
from http.server import BaseHTTPRequestHandler,HTTPServer

class RequestHandler(BaseHTTPRequestHandler):
    '''处理请求并返回页面'''
    # 页面模板
    Page = '''
            <html>
            <body>
            <table>
            <tr>  <td>Header</td>         <td>Value</td>          </tr>
            <tr>  <td>Date and time</td>  <td>{date_time}</td>    </tr>
            <tr>  <td>Client host</td>    <td>{client_host}</td>  </tr>
            <tr>  <td>Client port</td>    <td>{client_port}</td> </tr>
            <tr>  <td>Command</td>        <td>{command}</td>      </tr>
            <tr>  <td>Path</td>           <td>{path}</td>         </tr>
            </table>
            </body>
            </html>
        '''

    def do_GET(self):
        page = self.create_page()
        self.send_content(page)

    def create_page(self):
        values = {
            'date_time': self.date_time_string(),
            'client_host': self.client_address[0],
            'client_port': self.client_address[1],
            'command': self.command,
            'path': self.path
        }
        page = self.Page.format(**values) #dict为参数的传递方式  **
        return page


    def send_content(self,page):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.send_header("Content-length", str(len(self.Page)))  # 字符串类型
        self.end_headers()
        self.wfile.write(page.encode()) #这里必须转化威字节(bytes)类型 否则报错




if __name__ == '__main__':
    print("server start...")
    serverAddr = ('',9999) #链接不上可能是端口号被占用 换个试试
    server = HTTPServer(serverAddr,RequestHandler)
    server.serve_forever()



3、增加了对路径的异常处理:

# _*_coding :utf-8 _*_
import httpie
import sys,os
from http.server import BaseHTTPRequestHandler,HTTPServer

class RequestHandler(BaseHTTPRequestHandler):
    '''处理请求并返回页面'''
    # 页面模板
    Page = '''
            <html>
            <body>
            <table>
            <tr>  <td>Header</td>         <td>Value</td>          </tr>
            <tr>  <td>Date and time</td>  <td>{date_time}</td>    </tr>
            <tr>  <td>Client host</td>    <td>{client_host}</td>  </tr>
            <tr>  <td>Client port</td>    <td>{client_port}</td> </tr>
            <tr>  <td>Command</td>        <td>{command}</td>      </tr>
            <tr>  <td>Path</td>           <td>{path}</td>         </tr>
            </table>
            </body>
            </html>
        '''
    Error_Page = """\
        <html>
        <body>
        <h1>Error accessing {path}</h1>
        <p>{msg}</p>
        </body>
        </html>
     """

    def do_GET(self):
        try:
            #文件完整路径
            full_path = os.getcwd() + self.path

            #如果该路径不存在...
            if not os.path.exists(full_path):
            # 抛出异常:文件未找到
                raise ServerException("'{0}' not found".format(self.path))

            # 如果该路径是一个文件
            elif os.path.isfile(full_path):
            # 调用 handle_file 处理该文件
                self.handle_file(full_path)

            # 如果该路径不是一个文件
            # 抛出异常:该路径为不知名对象
            else:
                raise ServerException("Unknown object '{0}'".format(self.path))
        except Exception as msg: #msg则是上面抛出的信息
            self.handle_error(msg)


    def create_page(self):
        values = {
            'date_time': self.date_time_string(),
            'client_host': self.client_address[0],
            'client_port': self.client_address[1],
            'command': self.command,
            'path': self.path
        }
        page = self.Page.format(**values) #dict为参数的传递方式  **
        return page


    def send_content(self,page): #这里不再是个server1一样了  需要传参数page
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.send_header("Content-length", str(len(self.Page)))  # 字符串类型
        self.end_headers()
        self.wfile.write(page.encode())       #这里必须转化威字节(bytes)类型 否则报错

    def handle_file(self,full_path):
        try:
            with open(full_path,"r") as reader:  #读字节 故在sent_content()中不需要转化为bytes了
                content = reader.read()
            self.send_content(content)
        except IOError as msg:
            msg = "'{0}' cannot be read :{1}".format(self.path,msg)
            self.handle_error(msg)
    def handle_error(self,msg):
        content = self.Error_Page.format(path = self.path,msg = msg)
        self.send_content(content)


class ServerException(Exception):

    '''服务器内部错误'''
    pass

if __name__ == '__main__':
    print("server start...")
    serverAddr = ('',9999) #链接不上可能是端口号被占用 换个试试
    server = HTTPServer(serverAddr,RequestHandler)
    server.serve_forever()

plain.html为自己创建的静态网页


4、增加了代码的重构,更加简明,易扩展

#-*- coding:utf-8 -*-
import sys, os, subprocess
from http.server import HTTPServer,BaseHTTPRequestHandler

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

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

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

class base_case(object):
    '''条件处理基类'''

    def handle_file(self, handler, full_path):
        try:
            with open(full_path, 'r') as reader: #这里不要直接读城b 的否则会与下面的decode冲突
                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(["python", handler.full_path])
        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>
        """

    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)

    def handle_error(self, msg):
        content = self.Error_Page.format(path=self.path, msg=msg)
        self.send_content(content, 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.encode())

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

if __name__ == '__main__':
    print("server start...")
    serverAddress = ('', 9999)
    server = HTTPServer(serverAddress, RequestHandler)
    server.serve_forever()

此时的 状态为 404了


参考:https://zhuanlan.zhihu.com/p/21323273?utm_source=qq&utm_medium=social

猜你喜欢

转载自blog.csdn.net/tianweidadada/article/details/80151248