文件结构
html/index.html
static #存放静态文件
templates/(index.html center.html) #框架模板
web/myWeb.py
webSwever.py
import time, re, socket, sys, multiprocessing
class WSGIServer(object):
def __init__(self, docRoot, app):
# 创建服务端连接
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 地址复用
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定地址和端口
self.s.bind(("", 8080))
# 主动连接改为被动监听
self.s.listen(128)
# 设置根目录
self.docRoot = docRoot
# 把创建来的app变为对象的app
self.app = app
# 运行服务器
def runServer(self):
while True:
# 接收客户端的请求
newS, _ = self.s.accept()
# newS.settimeout(3)
# 创建新进程,处理客户端请求
newProcess = multiprocessing.Process(target=self.dealWithRequest, args=(newS,))
# 启动子进程
newProcess.start()
# 设置动态数据的请求头
def setResponse(self, status, headers):
# 设置默认请求头的数据
responseHeaderDefault = [
("Data", time.ctime()),
("Server", "LINUX-python mini web server")
]
# 拼接响应头部数据
self.headers = [status, responseHeaderDefault + headers]
# 设置定义处理客户端请求的函数
def dealWithRequest(self, newS):
while True:
try:
# 接受客户端的数据
content = newS.recv(1024).decode("utf-8")
# 捕获异常
except Exception as ret:
print("========>", ret)
newS.close()
return
# 判断客户端是不是要关闭连接
if not content:
# 没数据关闭连接
newS.close()
return
# 处理数据,进行行切片
requestLines = content.splitlines()
# 获取网站的请求路径
ret = re.match("[^/]+(/[^ ]*)", requestLines[0])
# 判断请求的路径
if ret.group(1) == "/":
# 如果是根路径,让他获取index页面
pathName = ret.group(1) + "index.html"
else:
# 如果不是根路径,返回原有路径赋值
pathName = ret.group(1)
# 处理静态请求
if not pathName.endswith(".py"):
# 异常处理
try:
f = open(self.docRoot + pathName, "r")
# 没有读取数据,捕获异常
except Exception as ret:
# 返回异常的响应头和响应体
responseBady = "file not found, Please input right url"
responseHeader = "HTTP/1.1 404 not found\r\n"
responseHeader += "Content-Type: text/html; charset=utf-8\r\n"
responseHeader += "Content-Length: %d\r\n" % (len(responseBady))
responseHeader += "\r\n"
# 拼接异常响应数据
response = responseHeader + responseBady
# 没有异常
else:
# 读取文件数据
content = f.read()
# 返回响应头和响应体
responseBody = content
responseHeader = "HTTP/1.1 200 OK\r\n"
responseHeader += "Content-Type: text/html; charset=utf-8\r\n"
responseHeader += "Content-Length: %d\r\n" % (len(responseBody))
responseHeader += "\r\n"
# 拼接响应数据
response = responseHeader + responseBody
# 将响应数据发送给客户端
newS.send(response.encode("utf-8"))
# 处理动态请求
else:
# 存储所有需要处理的请求的kv
requestDict = {"pathName": pathName}
# 通过myWeb下的app函数处理动态请求,获取响应数据
responseBody = self.app(requestDict, self.setResponse)
# 设置响应头
responseHeader = "HTTP/1.1 {status}\r\n".format(status=self.headers[0])
responseHeader += "Content-Type: text/html; charset=utf-8\r\n"
responseHeader += "Content-Length: %d\r\n" % len(responseBody)
# 设置响应头
for tempHead in self.headers[1]:
responseHeader += "{0}:{1}\r\n".format(*tempHead)
# 拼接响应数据
response = responseHeader + "\r\n" + responseBody
# 发送给客户端
newS.send(response.encode("utf-8"))
# 设置静态资源访问的路径
gStaticDocumentRoot = "./html"
# 设置动态资源访问的路径
gDynamicDocumentRoot = "./web"
# 定义服务器的入口
def main():
# 判断程序参数符不符合要求
if len(sys.argv) == 2:
# 获取程序的参数,获取要执行的函数名
webModuleAppName = sys.argv[1]
else:
print("Please input like 'python fileName modelName:applicationName'")
# 导入程序传参模块名以及应用名
ret = re.match(r"([^:]*):(.*)", webModuleAppName)
# 获取模块以及模块名
modelName = ret.group(1)
appName = ret.group(2)
# 添加模块路径到代码环境变量中
sys.path.append(gDynamicDocumentRoot)
# 导入模块名
model = __import__(modelName)
# 将模块内的app应用变成可用的对象或者函数
app = getattr(model, appName)
# 初始化对象并运行服务器
http = WSGIServer(gStaticDocumentRoot, app)
http.runServer()
if __name__ == "__main__":
main()
web/myWeb.py
import time, re
# 定义模板文件存放位置
templateRoot = "./templates"
# 返回请求index.py获取的文件
def index(fileName):
# 异常处理
try:
# 将文件名的后缀替换为.html
fileName = fileName.replace(".py", ".html")
# 打开文件
f = open(templateRoot + fileName)
# 捕获异常
except Exception as ret:
return "%s" % ret
# 返回数据
else:
# 保存打开的数据
content = f.read()
# 关闭打开的文件
f.close()
# 准备替换的数据
dataFromMysql = "等待数据中....(>_<)\n %s" % time.ctime()
# 进行模板数据替换
content = re.sub(r"\{%content%\}", dataFromMysql, content)
# 返回数据
return content
# 返回请求center.py获取的文件
def center(fileName):
# 异常处理
try:
# 将文件名的后缀替换为.html
fileName = fileName.replace(".py", ".html")
# 打开问文件
f = open(templateRoot + fileName)
# 捕获异常
except Exception as ret:
return "%s" % ret
# 返回数据
else:
# 保存读取的数据
content = f.read()
# 关闭打开的文件
f.close()
# 准备替换的文件
dataFromMysql = "无法显示数据(>_<)\n %s " % time.ctime()
# 进行模板数据替换
content = re.sub(r"\{%content%\}", dataFromMysql, content)
# 返回数据
return content
def app(requestDict, setResponse):
# 定义状态码
status = 200
# 定义响应头
responseHeader = [('Content-Type', 'text/html')]
# 设置返回的响应头
setResponse(status, responseHeader)
# 获取客户端请求路径
pathName = requestDict["pathName"]
# 根据客户端的请求,返回相应的请求页面
if pathName == "/index.py":
# 调用处理index页面的函数
return index(pathName)
elif pathName == "/center.py":
# 调用处理center页面的函数
return center(pathName)
else:
# 没有页面返回的数据
return str(requestDict) + 'sorry! requeset page not found--->%s\n' % time.ctime()
templates/index.html
{%content%}
<br>
<li>this is index.html</li>
templates/center.html
{%content%}
<br>
<li>this is center.html</li>
html/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>为 HTML 添加新元素</title>
<script>
document.createElement("myHero")
</script>
<style>
myHero {
display: block;
background-color: #ddd;
padding: 50px;
font-size: 30px;
}
</style>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落</p>
<myHero>我的第一个新元素</myHero>
</body>
</html>