Python Socket服务器如何过滤多余重复的GET请求
问题根因
现代浏览器访问任意HTTP服务时,会自动发起路径为/favicon.ico的GET请求拉取站点图标,用于标签页、收藏夹展示,该请求由浏览器内置逻辑触发,和用户手动操作、服务端代码逻辑无关。
异常触发的直接原因是服务端代码存在两处逻辑缺失:
- 未做请求路径路由判断,所有入站请求都会进入数字计算逻辑
- 未对提取到的路径末位字符做格式校验,直接强转为整数,处理
/favicon.ico请求时取到路径末尾非数字字符o,触发ValueError: invalid literal for int() with base 10: 'o'异常。
问题复现素材
抓取到的请求报文
GET /fd4 HTTP/1.1 Host: 127.0.0.1 Connection: keep-alive Cache-Control: max-age=0 sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7 Traceback (most recent call last): File "C:/Networks/hed/server_to_fix_problem.py", line 29, in <module> main() File "C:/Networks/hed/server_to_fix_problem.py", line 25, in main handle_client_G(client_socket) GET /favicon.ico HTTP/1.1 File "C:/Networks/hed/server_to_fix_problem.py", line 13, in handle_client_G number_to_return = int(URL[-1]) + 1 ValueError: invalid literal for int() with base 10: 'o' Host: 127.0.0.1 Connection: keep-alive sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102" sec-ch-ua-mobile: ?0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36 sec-ch-ua-platform: "Windows" Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: no-cors Sec-Fetch-Dest: image Referer: http://127.0.0.1/fd4 Accept-Encoding: gzip, deflate, br Accept-Language: he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7
第一条为用户主动发起的预期请求,第二条为浏览器自动触发的favicon请求。
存在问题的原始服务端代码
import socket def handle_client(client_socket): client_request = client_socket.recv(1024).decode() URL = "" for i in client_request[5::]: if i != " ": URL += i else: break print(client_request) number_to_return = int(URL[-1]) + 1 client_socket.send(str(number_to_return).encode()) client_socket.close() def main(): server_socket = socket.socket() server_socket.bind(("0.0.0.0", 80)) server_socket.listen() while True: client_socket, client_address = server_socket.accept() handle_client(client_socket) if __name__ == '__main__': main()
测试访问地址
http://127.0.0.1:80/5
修复方案
在请求处理逻辑前增加两层校验即可解决问题:
- 优先拦截
/favicon.ico请求,返回HTTP 204无内容状态码,符合浏览器预期 - 对提取到的路径末位字符做数字合法性校验,非法路径直接返回400错误,避免类型转换异常
另外原代码响应未拼接标准HTTP协议头,部分浏览器会判定响应无效,修复时需要补充标准响应头。
修复后的完整代码:
import socket def handle_client(client_socket): client_request = client_socket.recv(1024).decode() URL = "" for i in client_request[5::]: if i != " ": URL += i else: break print(client_request) # 过滤favicon请求 if URL == "/favicon.ico": response = "HTTP/1.1 204 No Content\r\n\r\n" client_socket.send(response.encode()) client_socket.close() return # 校验路径末位是否为合法数字 last_char = URL[-1] if not last_char.isdigit(): response = "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nInvalid request path" client_socket.send(response.encode()) client_socket.close() return number_to_return = int(last_char) + 1 # 拼接标准HTTP响应头 response = f"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n{number_to_return}" client_socket.send(response.encode()) client_socket.close() def main(): server_socket = socket.socket() server_socket.bind(("0.0.0.0", 80)) server_socket.listen() while True: client_socket, client_address = server_socket.accept() handle_client(client_socket) if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者tony
相关产品推荐
相关产品推荐

