XML上传接口A/B测试需先缓存原始字节再分发解析,避免请求体重复读失败;分流须在解析前完成,用请求头或Query参数而非XML内容;须确保AB两路解析器行为、编码、校验完全一致。
XML上传接口的A/B测试必须绕过「请求体不可重复读」陷阱
HTTP请求体(request.body)在多数Web框架中只能被读取一次。直接对同一请求做两次XML解析(A路和B路各一次)会失败——第二读返回空,导致B路逻辑拿不到数据。这不是设计问题,是流式IO的底层限制。
- Python Flask/FastAPI:调用
request.body或await request.body()后,后续再读就是空字节 - Java Spring Boot:
request.getInputStream()被消费后,再次调用抛IllegalStateException - Node.js Express:
req.pipe()或req.on('data')消费后无法重放
先缓存原始XML字节,再分发给A/B两套逻辑
核心动作是「在框架解析前,把原始字节拷贝一份并暂存内存或临时缓冲区」,之后A路和B路各自从副本解析,互不干扰。不是复制解析后的对象,而是复制未解析的原始字节流。
- Flask示例:用
request.get_data(cache=True)获取完整字节,再传给两套XML解析逻辑 - FastAPI:用
await request.body()一次,结果赋值给变量,后续A/B都基于该bytes对象解析 - Spring Boot:注册
ContentCachingRequestWrapper包装原始HttpServletRequest,再通过getContentAsByteArray()多次获取
from xml.etree import ElementTree as ETxml_bytes = await request.body() # 只读一次 tree_a = ET.fromstring(xml_bytes) tree_b = ET.fromstring(xml_bytes) # 安全:bytes可重复解析
分流策略不能依赖XML内容以外的字段
A/B测试分流必须在XML解析前完成,否则就失去了「同输入、不同处理路径」的对照意义。如果用XML里的 做哈希分流,但A路解析出错而B路成功,会导致同一请求被错误归入不同实验组——这会让指标不可比。