【捉虫记】第2期 在HTTP中,为什么MIME为application/*+xml有可能导致乱码
笔者在做RSS订阅时,发现了部分订阅链接在浏览器上打开后显示乱码。并且经过测试后,发现这个问题并非编码错误那么简单。遂做记录
最让人熟知的application/*+xml应该是两种流行的RSS订阅格式:application/rss+xml和application/atom+xml
事先说明,因为xml作为rss的中间载体,不会直接面向最终用户,所以不管浏览器怎么显示这个xml都无所谓,只要RSS订阅器能正确解析xml即可,从这个角度讲,讨论没有意义。所以本文的重点在于分析为什么2025年了,浏览器显示xml还会出现乱码
所有数据都在chrome和edge(都基于 Chromium)上测试,Firefox因为会直接把此类MIME直接下载为文件而排除在外
我们拿几个rss链接来测试,并取出其响应头的Content-Type
RSS源 | 链接 | Content-Type | 测试结果 |
---|---|---|---|
阮一峰的网络日志 | http://www.ruanyifeng.com/blog/atom.xml | application/xml | √ |
IT之家 | https://www.ithome.com/rss/ | text/xml; charset=utf-8 | √ |
小众软件 | https://feeds.appinn.com/appinns/ | application/rss+xml; charset=utf-8 | √ |
腾讯安全响应中心 | https://security.tencent.com/index.php/feed/blog/0 | application/rss+xml | 乱码 |
其中只有腾讯安全响应中心的显示内容是乱码,如下图所示,xml中已经指定了编码为utf-8
从上面表格一对比,貌似问题不是出在xml上,而是响应头Content-Type内容少了charset编码
通过本地Python+Bottle进行模拟测试得到如下结果
的确通过添加charset编码可以解决
那这里问题就来了,在Content-Type缺少编码的情况下,为什么浏览器不会从xml去获取编码?
如果细心留意,可以发现,其实application/rss+xml
类型的响应内容,并不会被浏览器认为是xml,而是当成了纯文本进行展示
我们可以通过一个真正的xml去对比
看到了吗?所以MIME=application/rss+xml
的响应内容,就算是规范的XML,里面写的编码,都被浏览器当做纯文本展示
那是不是rss+xml这个标准的实现有问题?经过查询,尽管RSS规范(https://www.rssboard.org/rss-mime-type-application.txt)约定rss的MIME为pplication/rss+xml
,但是在MIME的标准(https://www.iana.org/assignments/media-types/media-types.xhtml)里,并没有找到,也就是MIME目前还不认可rss+xml
。问题会在这里么?
并不是,因为在MIME的标准里,有atom+xml
这一类型,我使用Python+bottle
对tom+xml
类型进行了测试,发现结论和rss+xml
完全一致
所以真正的问题在于浏览器对*+xml
的实现,浏览器并不把基于xml进行数据格式规约的*+xml
当做xml,可能是基于XMl扩展类型太多(光MIME已规范的就有452种),其中部分还包含可执行代码(比如xml-patch+xml
),这会导致安全隐患。所以对于XHTML+XML、XML两者外的其他XML扩展,一律当纯文本展示
经过多组组合测试,结论如下
对于响应头是application/xml
的,浏览器可以完美进行解码。
但是对于application/*+xml
,浏览器按纯文本展示。而上文说的那个乱码,即是浏览器猜测编码不对导致的。所以如果要用*+xml
,一定要传递编码,如application/atom+xml;charset=utf-8
,才能避免浏览器猜错编码导致乱码
这里顺带提一下Opera,现在的Opera同样基于Chromium开发,同时它自身支持RSS订阅(会把RSS订阅链接解析成新闻加入到个人化新闻页面中)
Opera不支持解析rss+xml和atom+xml,只支持xml(即content-type
为application/xml
)
最让人绷不住的是,Opera解析XML乱成一锅粥。下面分别是用不同编码数据流,响应头指定编码,XML指定编码,只有数据流编码=GBK和XML编码encoding='GBK'同时满足时
才不会出现乱码,其他编码,要不就是标题乱码,要不就是内容乱码,再不就是全部乱码。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭