接口返回的富文本在客户端显示成 <p> 开头,而不是段落。用浏览器直接打开同一个接口地址,显示又是正常的。乍看像缓存或者权限的锅,追下去往往不是。

python3 -c "import html;s='<p>';print(html.unescape(s), html.unescape(html.unescape(s)))"
curl -s 'http://127.0.0.1:8080/api/rich?id=7' | head -c 200

追下去是这么回事:服务端拼接时先对内容转义了一次,写进 XML 时序列化器又整体转义一次,& 变成 &。解析一遍之后剩下的还是实体形式,客户端按文本显示就成了源码。

碰到「XML 实体转义」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。

线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

具体做法是,确认内容在哪一层做了 escape 只保留序列化那一层;拼 XML 用 DOM 或模板引擎 不要字符串相加;已经存坏的历史数据反解一次再重新入库;对比同一字段在 JSON 和 XML 两个接口的返回。

验收就看一点,客户端渲染出真正的段落 接口原文里只剩一层 <p>。

作者 9823189