request.data是只读一次的原始字节流,适合xml/二进制数据;request.get_data()可多次读取但默认不缓存,混用request.form会清空request.data,解析xml需注意编码、bom、xxe等细节。

Flask里request.data和request.get_data()的区别
直接读request.data最省事,但得知道它只读一次;如果中间有其他代码调用了request.get_data()、request.form或request.json,request.data就变空了。
-
request.data是原始字节流,没被解析过,适合XML/二进制等非表单数据 -
request.get_data(cache=True)能多次读,但默认cache=False,第二次调就返回空bytes - 别在同一个请求里混用
request.form和request.data——Flask会自动按Content-Type尝试解析,一碰就清空原始体
Content-Type不是application/xml时request.data可能为空
Flask默认只把application/x-www-form-urlencoded和multipart/form-data当表单处理,其他类型才保留原始体。但如果客户端发的是text/xml或application/soap+xml,request.data仍可用,只是得手动处理编码。
- 检查
request.headers.get('Content-Type'),确认是不是XML类MIME(比如含xml或soap) - 用
request.get_data(as_text=True)会自动按charset解码,但XML声明里的编码(如<?xml version="1.0" encoding="GBK"?>)它不认——得先读bytes,再用xml.etree.ElementTree.fromstring()或lxml解析 - 如果客户端没设Content-Type,Flask可能把body当
application/octet-stream,此时request.data仍有效,但得自己猜编码
用xml.etree.ElementTree解析时的常见报错
最常见的错误是ParseError: not well-formed (invalid token),基本都是编码不匹配或BOM头导致的。
- 先用
request.get_data()拿到bytes,不要用as_text=True——避免Python按默认UTF-8解码损坏原始字节 - 如果XML带BOM(比如
b'\xef\xbb\xbf<?xml... '),ElementTree.fromstring()会直接报错,得先切掉:data.strip().replace(b'\xef\xbb\xbf', b'') - 中文Windows环境常发GBK编码XML,
fromstring(data)会崩,得显式解码:fromstring(data.decode('gbk')),但更稳的做法是交给lxml:它能自动识别XML声明里的encoding -
ElementTree不支持DTD和外部实体,如果XML里有/code>或<code>&entity;,会报错或被忽略——生产环境建议用defusedxml替代原生模块防XXE
路由函数里怎么安全地收XML并返回响应
别图省事用@app.route('/api', methods=['POST'])然后硬写逻辑,容易漏掉边界检查。
立即学习“Python免费学习笔记(深入)”;
- 明确限定方法和MIME:
@app.route('/api', methods=['POST'], endpoint='xml_api'),并在视图里校验request.method == 'POST'和'xml' in request.headers.get('Content-Type', '') - 用
try/except xml.etree.ElementTree.ParseError捕获解析失败,返回400 Bad Request而不是500 - 返回XML响应时,别只写
return response_text,要加content_type='application/xml; charset=utf-8',否则浏览器可能当HTML渲染 - 如果XML结构固定,建议用
pydantic或dataclasses做反序列化,比手扒.find()更可靠
request.data接住、判断、解码、喂给XML库——最容易被忽略的是Content-Type未匹配时的静默失败,以及GBK/BOM/XXE这些编码和安全细节。










