完整代码
DjangoWeb.py代码
# coding:utf-8
import time
#from MyWebServer import HttpServer
import re
#常量名字要大写
HTML_ROOT_DIR = "./html"
#得到当前系统时间
def get_time(env,start_response):
#调用传入进来的start_response函数,
#并且调用的时候把当运行状态的相关状态给服务器
status = "200 OK"
headers = [
("Content-Type","Text/plain")
]
start_response(status,headers)
#返回前系统时间
return "Django_"+time.ctime()
#得到字符串hello atguigu
def get_hello(env,start_response):
#调用传入进来的start_response函数,
#并且调用的时候把当运行状态的相关状态给服务器
status = "200 OK"
headers = [
("Content-Type","Text/plain")
]
start_response(status,headers)
#返回Django_hello atguigu
return "Django_hello atguigu"
#得到字符串I love you!
def say_love(env,start_response):
#调用传入进来的start_response函数,
#并且调用的时候把当运行状态的相关状态给服务器
status = "200 OK"
headers = [
("Content-Type","Text/plain")
]
start_response(status,headers)
#返回hello atguigu
return "Django_I love you!"
class Application(object):
"""框架的核心部分,也是框架的主体程序,框架是通用的"""
def __init__(self,urls):
#接收路由信息
self.urls = urls
def __call__(self, env, start_response):
#得到要执行的函数(路径)
#可能得到/ctime或者/hello
path = env.get("PATH_INFO","/")
#/static/index.html
if path.startswith("/static"):
# /static/index.html-->/index.html
file_name = path[7:]
try:
# 打开文件读取/html/index.html文件内容,以二进制方式
f = open(HTML_ROOT_DIR + file_name, "rb")
except: # 文件没有找到返回404
# 1.响应状态
statu = "HTTP/1.1 404 Not Found"
# 2.响应头信息
headers = [
("Content-Type", "Text/plain")
]
# 生成响应头
start_response(statu, headers)
# 返回响应体内容
return "Not Found,Sorry!"
else:
# 文件存在,正常处理
file_data = f.read()
# 关闭文件
f.close()
# 1.响应状态
statu = "200 OK"
# 2.响应头信息
headers = []
# 生成响应头
start_response(statu, headers)
# 返回响应体内容
return file_data.decode("utf-8")
for url,function in self.urls:
#("/ctime", get_time)
#url对应的是/ctime;function对应的是get_time
if path == url:#判断是否是调用的函数
#返回的是响应体的内容
response_body = function(env,start_response)
print("response_body:",response_body)
#之间返回
return response_body
#拼接错误处理:响应头和响应体-----
#1.响应状态
statu = "404 Not Found"
#2.响应头信息
headers = [
("Content-Type", "Text/plain")
]
#生成响应头
start_response(statu,headers)
#返回响应体内容
return "Django_Not Found,Sorry!"
#路由信息
urls = [
# 当http://192.168.1.27:7788/ctime就是调用get_time方法
("/", get_time),
("/ctime", get_time),
("/hello", get_hello),
("/love", say_love)
]
#django_app变成了DjangoWeb.py模块中的属性
django_app = Application(urls)
'''
if __name__ == "__main__":
#路由信息
urls = [
# 当http://192.168.1.27:7788/ctime就是调用get_time方法
("/", get_time),
("/ctime", get_time),
("/hello", get_hello),
("/love", say_love)
]
app = Application(urls)
# 创建MyWebServer模块中的HttpServer类
http_server = HttpServer(app)
http_server.bind(7788)
http_server.start()
'''
MyWebFramework.py代码
#coding=utf-8
import socket
from multiprocessing import Process
import re
import sys
from MyWebFramework import Application
#常量名字要大写
HTML_ROOT_DIR = "./html"
WSGI_ROOT_DIR = "./wsgi"
class HttpServer(object):
def __init__(self,application):
self.app = application
# 创建TCP服务端
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 服务端口可以重复启动,不会被占用
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def bind(self,port):
# 绑定端口
self.server.bind(("", port))
def start(self):
# 设置监听
self.server.listen(128)
while True:
client_socket, client_address = self.server.accept()
# print("[%s %s]客户已经链接上了"%(client_address[0],client_address[1]))
print("[%s %s]客户已经链接上了" % client_address)
client = Process(target=self.handle_client, args=(client_socket,))
client.start()
# 在主进程中关闭链接
client_socket.close()
#根据运行python程序的情况,组织响应给浏览器的头对应信息
def start_response(self,status,headers):
"""status = "200 OK"
headers = [
("Content-Type","Text/plain")
]
"""
response_headers = "HTTP/1.1 " + status + "\r\n"
for header in headers:
response_headers += "%s: %s"%header+"\r\n"
#这样赋值给实例对象的response_header,其他地方就能使用了
self.response_header = response_headers
def handle_client(self,client_socket):
# 获取客户端请求的数据
request_data = client_socket.recv(1024)
request_lines = request_data.splitlines()
for line in request_lines:
print(line)
# 从b'GET /index.html HTTP/1.1或者b'GET / HTTP/1.1
request_start_line = request_lines[0].decode("utf-8")
# 使用正则表达式,得到请求路径/或者/index.html
file_path = re.match(r"\w+ +(/[^ ]*)", request_start_line)
file_name = file_path.group(1)
## 从b'GET /index.html HTTP/1.1或者b'GET / HTTP/1.1
# 得到请求方法GET或者POST等
method = re.match(r"(\w+) +/[^ ]*", request_start_line).group(1)
env = {"PATH_INFO":file_name,
"METHOD":method
}
response_body = self.app(env, self.start_response)
# 组织响应数据response = 响应头 + 响应体
response = self.response_header + "\r\n" + response_body
print("file_name:", file_name)
print("response data:", response)
#client_socket.send(bytes(response,"utf-8"))
client_socket.send(response.encode("utf-8"))
client_socket.close()
def main():
sys.path.insert(1,WSGI_ROOT_DIR)
if len(sys.argv) < 2:
sys.exit("您还没有配置:python3 MyWebServer.py Module:app")
#python3 MyWebServer.py MyWebFramework:app
#得到MyWebFramework:app
argvs = sys.argv[1]
#拆分成:
#module_name = "MyWebFramework"
#app_name = "app"
module_name,app_name = argvs.split(":")
#导入模块
m = __import__(module_name)
#使用getattr(模块,要加载模块的属性或者类)
#app就是Application类 实例化好的对象,并且传入了路由信息
app = getattr(m,app_name)
#实例化MyWebFramework.py中的Application类
#app = Application(urls)
http_server = HttpServer(app)
http_server.bind(7788)
http_server.start()
if __name__ == "__main__":
main()
MyWebFramework.py代码
# coding:utf-8
import time
#from MyWebServer import HttpServer
import re
#常量名字要大写
HTML_ROOT_DIR = "./html"
#得到当前系统时间
def get_time(env,start_response):
#调用传入进来的start_response函数,
#并且调用的时候把当运行状态的相关状态给服务器
status = "200 OK"
headers = [
("Content-Type","Text/plain")
]
start_response(status,headers)
#返回前系统时间
return time.ctime()
#得到字符串hello atguigu
def get_hello(env,start_response):
#调用传入进来的start_response函数,
#并且调用的时候把当运行状态的相关状态给服务器
status = "200 OK"
headers = [
("Content-Type","Text/plain")
]
start_response(status,headers)
#返回hello atguigu
return "hello atguigu"
#得到字符串I love you!
def say_love(env,start_response):
#调用传入进来的start_response函数,
#并且调用的时候把当运行状态的相关状态给服务器
status = "200 OK"
headers = [
("Content-Type","Text/plain")
]
start_response(status,headers)
#返回hello atguigu
return "I love you!"
class Application(object):
"""框架的核心部分,也是框架的主体程序,框架是通用的"""
def __init__(self,urls):
#接收路由信息
self.urls = urls
def __call__(self, env, start_response):
#得到要执行的函数(路径)
#可能得到/ctime或者/hello
path = env.get("PATH_INFO","/")
#/static/index.html
if path.startswith("/static"):
# /static/index.html-->/index.html
file_name = path[7:]
try:
# 打开文件读取/html/index.html文件内容,以二进制方式
f = open(HTML_ROOT_DIR + file_name, "rb")
except: # 文件没有找到返回404
# 1.响应状态
statu = "HTTP/1.1 404 Not Found"
# 2.响应头信息
headers = [
("Content-Type", "Text/plain")
]
# 生成响应头
start_response(statu, headers)
# 返回响应体内容
return "Not Found,Sorry!"
else:
# 文件存在,正常处理
file_data = f.read()
# 关闭文件
f.close()
# 1.响应状态
statu = "200 OK"
# 2.响应头信息
headers = []
# 生成响应头
start_response(statu, headers)
# 返回响应体内容
return file_data.decode("utf-8")
for url,function in self.urls:
#("/ctime", get_time)
#url对应的是/ctime;function对应的是get_time
if path == url:#判断是否是调用的函数
#返回的是响应体的内容
response_body = function(env,start_response)
print("response_body:",response_body)
#之间返回
return response_body
#拼接错误处理:响应头和响应体-----
#1.响应状态
statu = "404 Not Found"
#2.响应头信息
headers = [
("Content-Type", "Text/plain")
]
#生成响应头
start_response(statu,headers)
#返回响应体内容
return "Not Found,Sorry!"
#路由信息
urls = [
# 当http://192.168.1.27:7788/ctime就是调用get_time方法
("/", get_time),
("/ctime", get_time),
("/hello", get_hello),
("/love", say_love)
]
#app变成了MyWebFramework.py模块中的属性
app = Application(urls)
'''
if __name__ == "__main__":
#路由信息
urls = [
# 当http://192.168.1.27:7788/ctime就是调用get_time方法
("/", get_time),
("/ctime", get_time),
("/hello", get_hello),
("/love", say_love)
]
app = Application(urls)
# 创建MyWebServer模块中的HttpServer类
http_server = HttpServer(app)
http_server.bind(7788)
http_server.start()