初学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 文件解读
- 里面有2个比较重要的类 , BaseHTTPRequestHandler , HTTPServer
- 自己编写一个requestHandler类,然后处理请求
- 这个类要覆盖下 do_GET 方法
- 给前端写的结果是 self.wfile.write(self.Page.encode('utf-8'))
- 要启动这个服务的时候需要这几行比较重要的代码
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')) 响应内容
运行结果:
浏览器输入:
第二版 使用静态文件制定响应内容
这个和当初的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 !')
启动程序,浏览器中输入