input标签有中文邮箱后缀名引发的问题

前提介绍

最近,在公司的某个项目中,测试人员发现了一个颇有意思的Bug。当用户的我的资料页面的邮箱联系方式是中文后缀时,例如"mi@测试.com",在Android原平生台上会显示乱码的现象,而在浏览器中显示则正常,结果以下面两张图所示。在另外一个同事寻找资料无果的状况下,因而,我开始了一步步分析这个问题的过程。
image.png
上图是Android设备
image.png
上图是浏览器中
html

分析过程    

由于两个环境中调用的都是同一个接口返回的数据,因此以我的多年的工做经验来看,这个问题多是编码方面的问题。因而,我列出了如下几种状况:浏览器

  1. Web端进行了转码,而后传入到后台服务器中,Android端拿到数据后,因为编码不一样,因此出现中文部分出现了乱码。
  2. Web端没有转码,可是后台服务器进行了转码,Android端拿到数据后,因为编码不一样,因此出现中文部分出现了乱码。
  3. Web端和后台服务都没有转码,Android端的输入框控件内部进行了一次转码,而后致使中文部分出现了乱码。
  4. Web端和后台服务器都进行了转码,也就是进行了两次转码,而后致使Android端出现中文部分了乱码的缘由。

针对以上的几种状况,我分别询问了各位同事和抓包看返回的数据,发现:一、Web端、服务器端都没有进行转码操做。二、在出现乱码的Android端,拿到的数据就是接口返回的原始数据。并且,我也尝试过对几种常见的编码进行转换操做,看看能不能找到问题所在,可是都不是我想要的结果。那,问题究竟在哪?
服务器

深刻分析的过程

在初次分析无果的状况下,我开始考虑会不会是由于Web端的使用的第三方框架的缘由。由于Web端使用了Element UI,有没有可能Element UI对<input />标签进行了二次封装,并进行了转码操做?同时,经Web端的同事提醒,<input />标签的type属性为"email"。因而,我决定,我直接新建了一个新的HTML文件,为了避免受其它影响,里面就只有一个<input />标签。
框架

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <input type="email" />
</body>

</html>


而后,在Chrome 浏览器中打开,输入测试字段"mi@测试.com"。结果显示一切正常,中文依然正确显示,彷佛没有任何问题。可是本着要打破砂锅问到底的精神,我试着在浏览器中改了一下标签的type值,我尝试着将"email"改为"text"。没想到,问题复现了。

https://www.bilibili.com/vide...ide

将type="email"改为type="text"之后,浏览器中中文部分会出现乱码,而再改回去之后,显示又一切正常。另外一方面,我试着在在Chrome控制台中获取input值,看看原始值究竟是什么。结果,也有了惊奇的发现。
image.png    此时input标签的type值依然是"email",但在控制台中打印出来的结果竟然是乱码的字符串,如今看来,问题的关键点颇有可能就是在这个type="email"上!
测试

为何是type="email"?

有过Web开发的同窗们应该对这个属性是很熟悉的了,至于type的其它类型,就不在本文中阐述了,咱们直接看MDN上关于<input type="email">的相关资料,试着去了解一下,当type="email"的时候,浏览器究竟作了什么?(更多细节能够点击这个连接进行查看)。网站


带有 "email" (电子邮箱)类型标记的输入框元素()可以让用户输入或编辑一个电子邮箱地址,此外,若是指定了multiple属性,用户还能够输入多个电子邮箱地址。在表单提交前,输入框会自动验证输入值是不是一个或多个合法的电子邮箱地址(非空值且符合电子邮箱地址格式). CSS伪标签 :valid 和 :invalid 可以在校验后自动应用。

根据引用MDN网站上的文字的描述,个人一个猜测是,多是浏览器在作验证的时候进行了转码操做,同时,我又看到网页中的这个相关描述。而后,我点击了DOMString来进行更深刻的了解。搜索引擎

image.png

DOMString 是一个UTF-16字符串。因为JavaScript已经使用了这样的字符串,因此DOMString 直接映射到 一个String

看到这两个描述,我第一反应是,难道"mix@测试.com"是被转码成了UTF-16?可是,转码后的字符串并非常见的UTF-16的格式。因此直觉告诉我,事情没有那么简单,这不是我想要的结果。因而我继续在当前的MDN网页上查看相关资料,在网页的下端,一段内容引发了个人注意。引发我注意的不只仅是那段正则,还有下面的提示--W3C bug 15489
image.png
打开连接后我发现W3C bug 15489 是2012年由一位叫 Mathias Bynens 外国工程师 提出来的问题,在这个讨论问题的帖子的页面中,我惊喜的发现,这个网页中所提的bug正是我苦苦寻找的问题所在。
image.png
顺着这个结果,我发现关键的线索--Punycode!我立马打开的新的网页,找一个在线Punycode编码的网站。BingGo!
image.png
编码

什么是Punycode?

那么,问题的因此在看来就是这个Punycode了,那什么是Punycode呢?引用百度百科的里的解释:spa

Punycode(译为:域名代码)是一种表示Unicode码和ASCII码的有限的字符集。例如:“münchen”(德国慕尼黑)会被编码为“mnchen-3ya”。

同时,了解到一个新的知识点--IDNs(国际化域名 Internationalized Domain Names)。早期的DNS是只支持英文域名解析。在IDNs推出之后,为了保证兼容之前的DNS,因此,对IDNs进行Punycode转码,转码后的Punycode就由26个字母+10个数字,还有“-”组成。
顺着这个,我接着往下看,这个页面里发现了一个更有意思和详细的资料。
image.png

最后的总结

因此,通过几乎1个小时的时间,通过各类资料的汇总,这个问题终于被摸清楚了。
在浏览器中type属性为email的input标签能正常显示中文后缀的缘由,是由于现代浏览器自动加入中文域名的转码。正如上文所说,是浏览器软件里面主动加入了中文域名自动转码,因此中文后缀才会显示正常。同时,这也就解释了为何在type="email"的状况下。浏览器控制台中获取的value会依然是乱码后的字符串。那么,既然知道问题的所在,解决的方法天然也很简单了,经过搜索引擎或者本身写一个关于Punycode转码的方法应该就能将问题顺利解决了。

相关文章
相关标签/搜索