介绍
使用web框架专门负责处理用户的动态资源请求,这个web框架其实就是一个为web服务器提供服务的应用程序,简称web框架
流程展示
说明
静态资源
动态资源
WSGI协议
框架程序开发
介绍
动态资源判断
获取处理结果
web.py 代码示例
import socket
import os
import threading
import sys
import framework
# http协议的web服务器类
class HttpWebServer(object):
def __init__(self, port):
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", port))
# 配置监听
tcp_server_socket.listen(128)
# 把tcp服务器的套接字作为web服务器对象的属性
self.tcp_server_socket = tcp_server_socket
# 处理客户端请求
@staticmethod
def handle_client_request(new_socket):
# 接收客户端的请求信息
recv_data = new_socket.recv(4096)
# 判断如果客户端请求是空数据,则直接关闭服务套接字
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制数据进行解码
recv_content = recv_data.decode("utf-8")
# 对数据按照空格进行分割
request_list = recv_content.split(" ", maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
# 打印查看获取到的资源路径
print(request_path)
# 判断请求的是否为根路径,如果是设置默认返回图片
if request_path == "/":
request_path = "/test.jpeg"
# 判断请求是否是动态请求(这里规定后缀.html是动态请求)
if request_path.endswith(".html"):
"""动态资源请求"""
# 动态资源请求给web框架处理,需要把请求参数给框架
# 准备给web框架的参数信息,放到字典里
env = {
"request_path": request_path,
# 需要的额外的参数在这个字典里进行添加
}
# 使用框架处理动态资源请求
# 1、web框架把处理结果返回给web服务器
# 2、web服务器把返回的结果封装成响应报文再返回给浏览器
status, headers, response_body = framework.handle_request(env)
print(status, headers, response_body)
else:
# 判断此文件是否存在
# 第一种方法:os.path.exists
# os.path.exists("web/" + request_path)
# 第二种方法:try-except
try:
# 准备返回数据
# 打开文件读取文件中的数据,with open关闭文件无需程序员操作,系统自动关闭
# 这里使用"rb"模式,兼容打开图片文件
with open("web" + request_path, "rb") as file: # file表示打开文件的对象
file_data = file.read()
except Exception as e:
# 代码执行到此,说明没有请求的文件资源,返回404状态信息
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: LAIFU/1.0\r\n"
# 读取404页面数据
with open("web/error.html", "rb") as file:
file_data = file.read()
# 响应体
response_body = file_data
# 把数据封装成http响应报文格式的数据
response = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送给客户端(浏览器)的响应报文数据
new_socket.send(response)
else: # 代码执行到此,说明访问文件资源存在,返回200状态信息
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: LAIFU/1.0\r\n"
# 响应体
response_body = file_data
# 把数据封装成http响应报文格式的数据
response = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送给客户端(浏览器)的响应报文数据
new_socket.send(response)
finally:
# 关闭服务与客户端的套接字
new_socket.close()
# 启动服务器的方法
def start(self):
# 循环等待接收客户端的连接请求
while True:
new_socket, ip_port = self.tcp_server_socket.accept()
sub_thread = threading.Thread(target=self.handle_client_request, args=(new_socket,))
# 设置成为守护主线程
sub_thread.setDaemon(True)
# 启动子线程执行对应的任务
sub_thread.start()
def main():
# 创建web服务器
web_server = HttpWebServer(8000)
# 启动服务器
web_server.start()
# 判断是否是主模块的代码
if __name__ == '__main__':
main()
framework.py 代码示例
"""web框架的职责:专门负责处理动态资源请求"""
import time
# 获取首页数据
def index():
# 状态信息
status = "200 OK"
# 响应头信息
response_header = [("Server", "LLF/1.1")]
# web处理后的数据
data = time.ctime()
# 这里返回的是元祖
return status, response_header, data
# 处理动态资源请求
def handle_request(env):
# 获取动态的请求资源路径
request_path = env["request_path"]
print("动态资源请求的地址:", request_path)
# 判断请求的动态资源路径,选择指定的函数处理对应的请求
if request_path == "/laifu.html":
# 获取首页数据
result = index()
# 把处理后的结果返回给web服务器(拼接报文时)使用
return result
输出
/laifu.html
动态资源请求的地址: /laifu.html
200 OK [('Server', 'LLF/1.1')] Tue Apr 19 11:34:00 2022
封装响应报文给浏览器
web.py 代码示例
import socket
import os
import threading
import sys
import framework
# http协议的web服务器类
class HttpWebServer(object):
def __init__(self, port):
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", port))
# 配置监听
tcp_server_socket.listen(128)
# 把tcp服务器的套接字作为web服务器对象的属性
self.tcp_server_socket = tcp_server_socket
# 处理客户端请求
@staticmethod
def handle_client_request(new_socket):
# 接收客户端的请求信息
recv_data = new_socket.recv(4096)
# 判断如果客户端请求是空数据,则直接关闭服务套接字
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制数据进行解码
recv_content = recv_data.decode("utf-8")
# 对数据按照空格进行分割
request_list = recv_content.split(" ", maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
# 打印查看获取到的资源路径
print(request_path)
# 判断请求的是否为根路径,如果是设置默认返回图片
if request_path == "/":
request_path = "/test.jpeg"
# 判断请求是否是动态请求(这里规定后缀.html是动态请求)
if request_path.endswith(".html"):
"""动态资源请求"""
# 动态资源请求给web框架处理,需要把请求参数给框架
# 准备给web框架的参数信息,放到字典里
env = {
"request_path": request_path,
# 需要的额外的参数在这个字典里进行添加
}
# 使用框架处理动态资源请求
# 1、web框架把处理结果返回给web服务器
# 2、web服务器把返回的结果封装成响应报文再返回给浏览器
status, headers, response_body = framework.handle_request(env)
print(status, headers, response_body)
# 响应行
response_line = "HTTP/1.1 %s\r\n" % status
# 响应头
response_header = ""
for header in headers:
response_header += "%s: %s\r\n" % header
# 响应报文
response_data = (response_line + response_header +
"\r\n" + response_body).encode("utf-8")
# 发送响应报文数据给浏览器
new_socket.send(response_data)
# 关闭连接
new_socket.close()
else:
# 判断此文件是否存在
# 第一种方法:os.path.exists
# os.path.exists("web/" + request_path)
# 第二种方法:try-except
try:
# 准备返回数据
# 打开文件读取文件中的数据,with open关闭文件无需程序员操作,系统自动关闭
# 这里使用"rb"模式,兼容打开图片文件
with open("web" + request_path, "rb") as file: # file表示打开文件的对象
file_data = file.read()
except Exception as e:
# 代码执行到此,说明没有请求的文件资源,返回404状态信息
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: LAIFU/1.0\r\n"
# 读取404页面数据
with open("web/error.html", "rb") as file:
file_data = file.read()
# 响应体
response_body = file_data
# 把数据封装成http响应报文格式的数据
response = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送给客户端(浏览器)的响应报文数据
new_socket.send(response)
else: # 代码执行到此,说明访问文件资源存在,返回200状态信息
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: LAIFU/1.0\r\n"
# 响应体
response_body = file_data
# 把数据封装成http响应报文格式的数据
response = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送给客户端(浏览器)的响应报文数据
new_socket.send(response)
finally:
# 关闭服务与客户端的套接字
new_socket.close()
# 启动服务器的方法
def start(self):
# 循环等待接收客户端的连接请求
while True:
new_socket, ip_port = self.tcp_server_socket.accept()
sub_thread = threading.Thread(target=self.handle_client_request, args=(new_socket,))
# 设置成为守护主线程
sub_thread.setDaemon(True)
# 启动子线程执行对应的任务
sub_thread.start()
def main():
# 创建web服务器
web_server = HttpWebServer(8000)
# 启动服务器
web_server.start()
# 判断是否是主模块的代码
if __name__ == '__main__':
main()
framework.py 代码示例
"""web框架的职责:专门负责处理动态资源请求"""
import time
# 获取首页数据
def index():
# 状态信息
status = "200 OK"
# 响应头信息
response_header = [("Server", "LLF/1.1")]
# web处理后的数据
data = time.ctime()
# 这里返回的是元祖
return status, response_header, data
# 处理没有找到的动态资源
def not_found():
# 状态信息
status = "404 Not Found"
# 响应头信息
response_header = [("Server", "LLF/1.1")]
# web处理后的数据
data = "Not Found"
# 这里返回的是元祖
return status, response_header, data
# 处理动态资源请求
def handle_request(env):
# 获取动态的请求资源路径
request_path = env["request_path"]
print("动态资源请求的地址:", request_path)
# 判断请求的动态资源路径,选择指定的函数处理对应的请求
if request_path == "/laifu.html":
# 获取首页数据
result = index()
# 把处理后的结果返回给web服务器(拼接报文时)使用
return result
else:
# 没有动态资源数据返回404
result = not_found()
return result
输出
/laifu.html
动态资源请求的地址: /laifu.html
200 OK [('Server', 'LLF/1.1')] Tue Apr 19 11:49:33 2022
/favicon.ico
/laifu1.html
动态资源请求的地址: /laifu1.html
404 Not Found [('Server', 'LLF/1.1')] Not Found