You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让BaseHTTPRequestHandler的分块流式PUT请求不丢字节?

问题分析与解决:分块PUT请求的同步阻塞问题

问题背景

以下是一个Python程序的MCVE示例,功能如下:

  • 启动时通过首个命令行参数设置全局变量FIXME;
  • 在单独线程启动HTTP服务器:
    • 通过对self.rfile.fileno()调用select监听分块PUT请求;
    • 打印接收的数据;
  • 主线程运行服务器客户端:
    • 若FIXME为True,休眠100毫秒;
    • 用requests模块发送含单行数据的分块PUT请求。

正常执行情况(FIXME=1)

$ ./test.py 1
SERVER SELECT
CLIENT write
SERVER RECV 13 b'3\r\n123\r\n0\r\n\r\n'
b'3\r\n123\r\n0\r\n\r\n'
127.0.0.1 - - [27/Nov/2023 11:14:01] "PUT / HTTP/1.1" 200 -

异常情况(FIXME=0)

程序阻塞且字节丢失(MCVE约10次尝试复现,实际程序必现):

$ ./1.py 0
CLIENT write
SERVER SELECT

疑问点

  1. 如何移除额外休眠?缺少什么同步机制?原因是什么?
  2. 推测客户端在服务器进入select前就传输/关闭了字节,但不解为何select无法处理套接字剩余字节。尝试设置set_blocking(inputfd, True)并调用os.read(inputfd,1)也无法读取,怀疑字节已被BaseHTTPRequestHandler读取,如何访问这些字节?

原因分析与解决方法

核心原因

问题出在**BaseHTTPRequestHandler的默认行为**和线程同步缺失:

  1. 当客户端在服务器线程进入select前就发送完数据时,BaseHTTPRequestHandler在调用自定义处理逻辑前,已经自动读取并解析了请求头部和分块数据(HTTP分块编码的解析是handler内部的默认流程)。
  2. 此时再对self.rfile.fileno()执行select,套接字已无可读数据,导致select永久阻塞。
  3. FIXME=1时的休眠只是让服务器线程先进入select等待,客户端后发送数据,刚好避开了handler提前读取的情况,属于临时的“碰运气”方案,并非真正解决问题。

解决步骤

1. 移除休眠,添加线程同步

用**事件(Event)**实现服务器与客户端的同步,确保客户端在服务器准备就绪后再发送请求:

import threading

# 定义同步事件
server_ready = threading.Event()

class CustomHandler(BaseHTTPRequestHandler):
    def do_PUT(self):
        # 通知客户端:服务器已准备好接收数据
        server_ready.set()
        # 后续处理逻辑...

# 主线程流程
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()
# 等待服务器准备就绪
server_ready.wait()
# 发送分块PUT请求
requests.put(url, data=chunked_data)

2. 正确获取分块数据:直接使用self.rfile

BaseHTTPRequestHandler已经完成了分块编码的解析,无需手动操作底层文件描述符。直接通过self.rfile读取即可:

def do_PUT(self):
    # 读取所有分块数据
    data = self.rfile.read()
    print(f"SERVER RECV {len(data)} {data}")
    self.send_response(200)
    self.end_headers()

如果需要流式读取,可循环调用self.rfile.read(size),直到返回空字节串(表示分块结束)。

3. 为何直接操作fileno读取不到数据?

self.rfile是带缓冲的IO对象,BaseHTTPRequestHandler解析请求时,已将数据读取到内部缓冲区中,底层套接字的文件描述符自然没有剩余数据。必须直接操作self.rfile,而非绕过它读取fileno。


内容的提问来源于stack exchange,提问作者KamilCuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:32:20