import socket
import re
import os
import sys
import mini_web_frame_3
"""
GET /a/b/c HTTP/1.1\r\n 请求行
Accept: text/html;iamge/jpeg....
Accept: text/html;iamge/jpeg....
\r\n
请求体
HTTP/1.1 200 OK\r\n
Server: fdfff
Content-type:cfdf\r\n
\r\n
响应体
"""
class HttpServer(object):
def __init__(self):
# 1、创建负责监听的socket
self.socket_watch = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2、设置地址重用
self.socket_watch.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 3、绑定监听的端口
self.socket_watch.bind(("localhost", 8888))
# 4、转为被动
self.socket_watch.listen(128)
def handle_client(self,socket_con):
"""
负责处理客户端的连接
接收客户端发送的请求报文
解析客户端发送的请求报文
返回响应报文
"""
request = socket_con.recv(4096).decode()
# print(request)
# 通过split函数,切割请求报文,获取请求行
request_lines = request.split("\r\n")
# print(request_lines)
# 获取请求行
requeset_line = request_lines[0]
# print(requeset_line)
# GET /a/b/c/d.html HTTP/1.1
#/ a / b / c / d.html
# favicon.ico
res = re.match(r"\w+\s+(\S+)",requeset_line)
path = res.group(1)
# path ="/Users/zhaojianyu/Desktop/hm_day02/www" + path
path = os.getcwd() + "/www" + path
# print(path)
# 如果访问的资源路径,服务器中不存在, return 404 # ......py
#key: value
if path.endswith(".py"): # WSGI
response_line = "HTTP/1.1 200 OK\r\n"
response_head = "Server: mini_web_frame v 1.0\r\n"
response_head += "Content-type:text/html;charset= utf-8\r\n"
# 1、浏览器发送了一个.p请求,服务器处理不了,将请求给web应用
# 2、web应用根据请求,来选择性的调用响应的函数处理
# 3、通过全路径获取文件名
file_name = os.path.basename(path).split('.')[0] #login.py
response_body = mini_web_frame_3.application(file_name)
response = response_line + response_head + "\r\n" +response_body
socket_con.send(response.encode())
socket_con.close()
return
else:
if not os.path.exists(path):
response_line = "HTTP/1.1 404 Not Found\r\n"
response_head = "Server:laozhao v3.0\r\n"
response_body = "request directory or file is not exist\r\n"
response = response_line + response_head + "\r\n" +response_body
socket_con.send(response.encode())
socket_con.close()
return
else:
# 要么是文件,要么是文件夹
# 判断用户请求的是文件
if os.path.isfile(path):
# 读取指定路径下的文件,并返回(响应报文)
response_line = "HTTP/1.1 200 OK\r\n"
response_head = "Server: laozhao v3.0\r\n"
file = open(path,"rb")
response_body = file.read()
file.close()
response = response_line.encode() + response_head.encode() + "\r\n".encode() +response_body
socket_con.send(response)
socket_con.close()
return
else:
#请求的文件夹资源,没有/
if not path.endswith("/"):
response_line = "HTTP/1.1 302 Found\r\n"
response_head = "Server: laozhao v3.0\r\n"
response_head += "Content-Type:text/html;charset=utf-8\r\n"
response_body = "重定向到"+path +"/"
response = response_line+ response_head +"\r\n" +response_body
socket_con.send(response.encode())
socket_con.close()
return
else:
# 请求的资源路径有斜线
# 1、我允许你访问我的默认文件
defualt_document = False
# 如果为True,则读取对应的默认文件
if defualt_document:
if os.path.exists(path+"index.html"):
file = open(path+"index.html","rb")
response_body =file.read()
file.close()
response_line = "HTTP/1.1 200 OK\r\n"
response_head = "Server: laozhao v3.0\r\n"
response = response_line.encode() + response_head.encode() +"\r\n".encode()+response_body
socket_con.send(response)
socket_con.close()
return
elif os.path.exists(path + "default.html"):
file = open(path + "default.html", "rb")
response_body = file.read()
file.close()
response_line = "HTTP/1.1 200 OK\r\n"
response_head = "Server: laozhao v3.0\r\n"
response = response_line.encode() + response_head.encode() + "\r\n".encode() + response_body
socket_con.send(response)
socket_con.close()
return
else:
response_line = "HTTP/1.1 404 Not Found\r\n"
response_head = "Server: laozhao v3.0\r\n"
response_body = "Not Found"
response = response_line + response_head +"\r\n" +response_body
socket_con.send(response.encode())
socket_con.close()
return
else:
# 判断是否开启了目录浏览
document_browsing = True
if document_browsing :
# 1、获取访问资源文件夹下所有的文件和文件夹(当前目录下)
list_names = os.listdir(path)
# 2、拼接HTML页面,返回给浏览器客户端
response_body = ""
for item in list_names:
response_body += "- " + item +"
"
response_body += "
"
response_line ="HTTP/1.1 200 OK\r\n"
response_head = "Server: laozhao v3.0\r\n"
response = response_line +response_head +"\r\n" +response_body
socket_con.send(response.encode())
socket_con.close()
return
# index.html default.html
# 2、如果不允许你访问我的默认文件,判断是否开启了目录浏览
# 3、如果开启了目录浏览,则拼接文件夹的列表,进行返回
# 4、如果没有开启目录浏览,404 提示............
# print(path)
# /Users/zhaojianyu/Desktop/hm_day02/www/favicon.ico
# /Users/zhaojianyu/Desktop/hm_day02/www/a/b/c/d.html
# 拼接响应报文
"""
响应行
响应头
空行
响应体
"""
"""
www.baidu.com
www.baidu.com/
www.baidu.com/index.html
www.baidu.com/a
www.baidu.com/a/b
结论:从路径是否有扩展名判断是文件或者是文件夹是不成立的。
服务器处理:
如果用户请求的是文件夹,
首先判断文件夹的结尾是否有 /(服务器认为,只有文件夹后加上/,才是访问文件夹的标准格式)
重定向到 带/的路径下
文件夹有/
1、如果说文件夹中有默认的文件,则给你返回默认的文件 index.html defalut.html
2、是否开启了目录浏览
"""
response_line = "HTTP/1.1 200 OK\r\n"
response_head = "Server:laozhao v1.0\r\n"
response_head += "Content-Type: text/html;charset=utf-8\r\n"
# 返回固定页面的web服务器
path = "/Users/zhaojianyu/Desktop/hm_day02/www/index.html"
file = open(path,"r")
response_body = file.read()
file.close()
response = response_line + response_head + "\r\n" + response_body
# send给客户端浏览器
socket_con.send(response.encode())
socket_con.close()
def run_server(self):
while True:
# 返回与客户端通信的socket和客户端的地址
socket_con, con_addr = self.socket_watch.accept()
print("客户端%s连接成功!!!!" % str(con_addr))
# handle_client
self.handle_client(socket_con)
def main():
# 1、创建HttpServer对象
# port = int(sys.argv[1])
http_server = HttpServer()
# 2、调用run_server方法
http_server.run_server()
if __name__ == '__main__':
main()