Python 3.6 HTTPServer请求异常求助:PostMan请求阻塞
看起来你遇到的是Python自带HTTPServer和Postman交互时的连接阻塞问题,这和浏览器与Postman的连接行为差异,以及HTTPServer的默认单线程特性直接相关。我来帮你拆解原因和解决方案:
问题根源
Python 3.6的HTTPServer默认是单线程、单连接处理模式,而且它的BaseHTTPRequestHandler默认支持HTTP Keep-Alive。浏览器通常在请求完成后会主动关闭连接,但Postman默认会复用TCP连接(开启Keep-Alive)。当你用Postman连续发送请求时,后续请求会复用同一个连接,但单线程服务器正忙着处理第一个请求,后续请求就会被挂起;等你再次发送请求时,可能触发了连接重置或者服务器处理完积压请求,就会出现"所有待处理请求完成"的假象,但之后复用连接的请求又会再次陷入阻塞。
解决方案
方案1:强制关闭Keep-Alive连接
在你的请求处理类(继承自BaseHTTPRequestHandler)的do_POST方法中,添加Connection: close响应头,让服务器告诉客户端不要复用连接,每个请求都使用新连接:
from http.server import HTTPServer, BaseHTTPRequestHandler import json class MyRequestHandler(BaseHTTPRequestHandler): def do_POST(self): # 读取请求数据 content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length) data = json.loads(post_data) # 这里写你的业务处理逻辑... # 设置响应头,强制关闭连接 self.send_response(200) self.send_header('Content-Type', 'application/json') self.send_header('Connection', 'close') # 关键:关闭Keep-Alive self.end_headers() # 返回响应内容 response = json.dumps({'status': 'success'}).encode('utf-8') self.wfile.write(response) if __name__ == '__main__': server_address = ('', 8081) httpd = HTTPServer(server_address, MyRequestHandler) print('Server running on port 8081...') httpd.serve_forever()
这样Postman每次请求都会新建连接,不会出现阻塞问题。
方案2:使用多线程HTTPServer
如果需要支持Keep-Alive和并发请求,可以改用ThreadingHTTPServer,它会为每个请求创建一个新线程,从根源上避免单线程阻塞:
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler import json class MyRequestHandler(BaseHTTPRequestHandler): def do_POST(self): content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length) data = json.loads(post_data) # 这里写你的业务处理逻辑... self.send_response(200) self.send_header('Content-Type', 'application/json') self.end_headers() response = json.dumps({'status': 'success'}).encode('utf-8') self.wfile.write(response) if __name__ == '__main__': server_address = ('', 8081) # 用ThreadingHTTPServer替代原生HTTPServer httpd = ThreadingHTTPServer(server_address, MyRequestHandler) print('Threaded server running on port 8081...') httpd.serve_forever()
这个方案更适合需要处理并发请求的场景,Postman的复用连接请求也能被正常处理。
额外注意点
你的前端JS代码中使用jQuery.post发送JSON数据,要确保服务器正确解析请求体。另外,注意PHP输出的服务器地址和端口是否正确,如果前端页面和HTTPServer不在同一域名下,需要在服务器添加CORS响应头,比如Access-Control-Allow-Origin: *来解决跨域问题。
内容的提问来源于stack exchange,提问作者user5151860

