初学servlet的时候,我们写一个简单的servelt响应页面的请求响应

那么python也一样,同样可以做一个简单的web服务器响应页面请求

需要的模块:

http.server

两个重要的类:

BaseHTTPRequestHandler : 需要继承的类,响应请求方法,类似HttpServlet
HTTPServer: 获取一个server 并启动 , 类似tomcat 的角色

第一版:简单的web服务器实现

sever.py 

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

# 使用http模块
from http.server import BaseHTTPRequestHandler , HTTPServer

class MyRequestHandler(BaseHTTPRequestHandler):
    '''接受页面的处理请求并返回页面'''

    # 页面模板
    Page = '''\
            <html>
            <body>
            <p>Hello, web!</p>
            </body>
            </html>
        '''

    # 处理一个GET请求
    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('utf-8'))


if __name__ == '__main__':
    print('server start on 127.0.0.1:8080...')
    serverAddress = ('127.0.0.1',8080)
    server = HTTPServer(serverAddress , MyRequestHandler)
    server.serve_forever()
    print('server is started success !')

sever.py 文件解读

  1. 里面有2个比较重要的类 , BaseHTTPRequestHandler , HTTPServer
  2. 自己编写一个requestHandler类,然后处理请求
  3. 这个类要覆盖下 do_GET 方法
  4. 给前端写的结果是 self.wfile.write(self.Page.encode('utf-8'))
  5. 要启动这个服务的时候需要这几行比较重要的代码
    serverAddress = ('127.0.0.1',8080)
    server = HTTPServer(serverAddress , MyRequestHandler)
    server.serve_forever()

处理请求:

 这个就是get方法和post方法了

self.send_response(200)  设置响应码为 200
self.send_header("Content-Type","text/html")
self.wfile.write(self.Page.encode('utf-8')) 响应内容

运行结果:

浏览器输入:

http://127.0.0.1:8080

 第二版 使用静态文件制定响应内容

这个和当初的jsp一样的,可以通过页面来制定 view

但是都需要读取这些制定的文件

python中要读取文件需要 os 模块的支持和 open函数支持

要获取一个文件句柄,自然就想到了 with 语句了

with open("/tmp/foo.txt") as file:
    data = file.read()

首先做一个 index.html 放于 page 目录下面

index.html

<html>
  <head>
    <title>Welcome Page</title>
  </head>
  <body>
    <h1>Welcome </h1>
    <p>hello qianyue !</p>
  </body>
</html>

下面再写一版 MyRequestHandler2

1.里面增加了 异常的处理页面和功能  handle_error

2. 将创建页面的功能单独抽取出来为   create_page  函数

3. 读取文件的功能单独抽取成为  handle_file 函数

4. 将响应的内容的功能单独抽取出来 为  send_content 函数

代码如下:

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

# 使用http模块
from http.server import BaseHTTPRequestHandler , HTTPServer
import sys , os
import ServerException


class MyRequestHandler2(BaseHTTPRequestHandler):
    '''接受页面的处理请求并返回页面'''

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

    #------------------- 创建页面的函数----------------------------
    def create_page(self):
        '''
        从静态文件里面读取页面模板
        self.path 保存了请求的相对路径,因为 MyRequestHandler2 继承自 BaseHTTPRequestHandler,
        它已将请求的相对路径保存在 self.path 中了
        :return: 读取页面模板的内容
        '''
        print('当前的self.path=' + self.path)
        full_path = os.getcwd() + self.path
        # 如果该路径不存在...
        if not os.path.exists(full_path):
            print(self.path + " is not exitst !!!")
            raise Exception(" '{0}' not found".format(self.path))

        # 如果该路径是一个文件
        elif os.path.isfile(full_path):
            # 从文件读取内容
            content = self.handle_file(full_path)
            return content

        else:
            # 抛出异常:该路径为不知名对象
            raise Exception("Unknown object '{0}'".format(self.path))


    #------------------- 编写异常处理函数----------------------------
    def handle_error(self, msg):
        '''
        error handle
        :param msg:
        :return:
        '''
        content = self.Error_Page.format(path=self.path, msg=msg)
        print("error content:"+content)
        #  handle_error 函数中的 content 内容被编码为二进制了,所以调用的send_content 里面不用再进行这个 content.encode了
        self.send_content(content.encode('utf-8'),404)

    #------------------- 编写文件处理函数----------------------------
    def handle_file(self,full_path):
        '''
        文件处理函数
        :param full_path:
        :return: 读取文件的内容
        '''
        try:
            with open(full_path,'rb') as reader:
                content = reader.read()
            return content
        except IOError as msg:
            msg = " '{0}' cannot be read : {1} ".format(self.path,msg)
            self.handle_error(msg)
            return None


    #------------------- 将要响应的内容单独抽取出来----------------------------
    def send_content(self,page,status=200):
        '''
        响应页面的内容
        :param page:
        :param status:
        :return:
        '''
        self.send_response(status)
        self.send_header("Content-Type", "text/html")
        if page == None:
            print(' page is None...')
            self.send_header("Content-Length", '0')
            self.end_headers()
        else:
            self.send_header("Content-Length", str(len(page)))
            self.end_headers()
            # send_content 函数中的 page 去掉了编码,因为调用的时候已经编码过了
            self.wfile.write(page)

    #------------------- 重新写的get函数----------------------------
    def do_GET(self):
        '''
        :return:
        '''
        try:
            page = self.create_page()
            self.send_content(page)
        except Exception as msg:
            self.handle_error(msg)


if __name__ == '__main__':
    print('server start on 127.0.0.1:8080...')
    serverAddress = ('127.0.0.1',8080)
    server = HTTPServer(serverAddress , MyRequestHandler2)
    server.serve_forever()
    print('server is started success !')

启动程序,浏览器中输入

http://127.0.0.1:8080/page/index.html

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐