开发小型HTTP服务器遇IndexError: list index out of range问题求助
解决HTTP服务器数组索引越界错误
问题说明
开发HTTP服务器时触发IndexError: list index out of range,报错指向请求解析环节的split()[1]操作。
报错信息
Traceback (most recent call last): File "/data/data/com.termux/files/home/SimpleHTTP/Generic/main.py", line 12, in <module> client.send(str(f"HTTP/1.1 200 OK \n\n{open(f'.{client.recv(1024).decode().splitlines()[0].split()[1]}', 'rb').read()}").encode('utf-8')) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ IndexError: list index out of range
原始代码
import socket #Make a socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(("0.0.0.0", 8080)) sock.listen(1) #Handling requests while True: #listening for client client, address = sock.accept() try: #reads file from response and makes a response client.send(str(f"HTTP/1.1 200 OK \n\n{open(f'.{client.recv(1024).decode().splitlines()[0].split()[1]}', 'rb').read()}").encode('utf-8')) #HTTP Response 404 except FileNotFoundError: client.send("HTTP/1.1 404 Not Found".encode("utf-8"))
问题根源
- 无请求校验:所有逻辑压缩在一行,未处理空请求、格式错误的请求。比如客户端断开连接时
recv()返回空字节,解码后无法拆分出有效请求行;非标准HTTP请求的请求行拆分后元素不足2个,访问[1]就会越界。 - 安全风险:直接拼接用户输入的路径,存在路径遍历攻击(如
../)风险。 - 数据损坏:二进制文件转字符串再编码,会破坏非文本文件的内容。
修复方案
优化后的代码
import socket import os from urllib.parse import unquote # 创建socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(("0.0.0.0", 8080)) sock.listen(1) print("服务器运行在 http://0.0.0.0:8080") # 处理请求循环 while True: # 接受客户端连接 client, address = sock.accept() print(f"来自 {address} 的连接") try: # 接收请求数据 request_data = client.recv(1024) if not request_data: client.close() continue # 解码并解析请求行 request_str = request_data.decode('utf-8', errors='replace') lines = request_str.splitlines() if not lines: raise ValueError("空请求") request_line = lines[0].strip() parts = request_line.split() if len(parts) < 2: raise ValueError("无效请求行格式") # 提取并安全处理路径 path = unquote(parts[1]) # 规范化路径,防止路径遍历 safe_path = os.path.normpath(os.path.join('.', path)) if not safe_path.startswith('./'): raise PermissionError("非法访问路径") # 读取文件内容 with open(safe_path, 'rb') as f: content = f.read() # 发送200响应及正确头信息 response_headers = b"HTTP/1.1 200 OK\r\n" response_headers += b"Content-Length: %d\r\n" % len(content) response_headers += b"\r\n" client.send(response_headers + content) except FileNotFoundError: client.send(b"HTTP/1.1 404 Not Found\r\n\r\n文件不存在") except (ValueError, PermissionError) as e: client.send(b"HTTP/1.1 400 Bad Request\r\n\r\n请求无效: " + str(e).encode('utf-8')) except Exception as e: client.send(b"HTTP/1.1 500 Internal Server Error\r\n\r\n服务器错误: " + str(e).encode('utf-8')) finally: client.close()
修复要点
- 拆分逻辑,逐步骤校验请求有效性,避免索引越界。
- 对路径解码、规范化,拦截路径遍历攻击。
- 使用
with语句安全操作文件,避免资源泄漏。 - 直接发送二进制文件内容,避免数据损坏。
- 扩展异常捕获范围,返回对应HTTP错误码。
- 确保客户端连接最终关闭,避免资源占用。
内容的提问来源于stack exchange,提问作者Jakub Bors
相关产品推荐
相关产品推荐

