86 lines
3.3 KiB
Python
86 lines
3.3 KiB
Python
import os
|
||
import socket
|
||
import urllib.parse
|
||
|
||
# 设置服务器的根目录
|
||
WEB_ROOT = os.path.abspath("../www")
|
||
|
||
def serve_file(client_socket:socket.socket, path):
|
||
# 解析请求的URL路径,移除开头的/,并处理URL编码
|
||
requested_path = urllib.parse.unquote(path)
|
||
if requested_path == "/":
|
||
requested_path = "/index.html" # 默认页面
|
||
|
||
# 构建文件的绝对路径
|
||
file_path = os.path.join(WEB_ROOT, requested_path.lstrip('/'))
|
||
|
||
# 获取安全的绝对路径,以确保它不会跳出根目录
|
||
safe_path = os.path.abspath(file_path)
|
||
if not safe_path.startswith(WEB_ROOT):
|
||
# 如果请求的路径不是根目录的子路径,则返回403 Forbidden
|
||
response = b"HTTP/1.1 403 Forbidden\r\n"
|
||
response += b"Content-Type: text/html\r\n"
|
||
response += b"\r\n"
|
||
response += b"<html><body><h1>403 Forbidden</h1></body></html>"
|
||
else:
|
||
try:
|
||
# 尝试打开并读取文件
|
||
with open(safe_path, "rb") as file:
|
||
content = file.read()
|
||
# 根据文件类型设置Content-Type(这里简化处理,仅对HTML进行了处理)
|
||
content_type = "text/html" if safe_path.endswith(".html") else "application/octet-stream"
|
||
response = b"HTTP/1.1 200 OK\r\n"
|
||
response += f"Content-Type: {content_type}\r\n".encode()
|
||
response += b"Content-Length: " + str(len(content)).encode() + b"\r\n"
|
||
response += b"\r\n"
|
||
response += content
|
||
except FileNotFoundError:
|
||
# 文件未找到,返回404响应
|
||
response = b"HTTP/1.1 404 Not Found\r\n"
|
||
response += b"Content-Type: text/html\r\n"
|
||
response += b"\r\n"
|
||
response += b"<html><body><h1>404 Not Found</h1></body></html>"
|
||
|
||
client_socket.send(response)
|
||
|
||
def start_server(host="0.0.0.0", port=80):
|
||
socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||
socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 允许地址重用
|
||
socket_server.bind((host, port))
|
||
socket_server.listen(5)
|
||
print(f"Server listening on {host}:{port}")
|
||
|
||
while True:
|
||
client_socket = None
|
||
try:
|
||
client_socket, address = socket_server.accept()
|
||
print(f"Connection from {address}")
|
||
|
||
# 接收客户端请求
|
||
request = client_socket.recv(1024).decode("utf-8")
|
||
if not request:
|
||
print("Empty request received.")
|
||
continue
|
||
|
||
# 解析HTTP请求的第一行获取请求路径
|
||
request_lines = request.split("\r\n")
|
||
if request_lines and len(request_lines[0].split(" ")) >= 3:
|
||
method, path, _ = request_lines[0].split(" ", 2)
|
||
# 根据路径返回相应的文件
|
||
serve_file(client_socket, path)
|
||
else:
|
||
print("Invalid request line:", request_lines[0])
|
||
# 关闭客户端连接
|
||
|
||
except ConnectionResetError:
|
||
print("Connection reset by peer.")
|
||
except Exception as e:
|
||
print(f"Unexpected error: {e}")
|
||
finally:
|
||
if client_socket:
|
||
client_socket.close()
|
||
|
||
if __name__ == "__main__":
|
||
start_server()
|
||
|