URL刺客现身,竟另有妙用!
工作中大家会接触到形形色色的 url
,有些完美遵循格式,有些却像刺客一样,冷不丁的给你一刀。
先介绍下我的惨痛经历,给大家避避坑,最后告诉大家一个 url
刺客的妙用。
刺客介绍
1. iOS WKWebview 刺客
此类刺客手段单一,只会影响 iOS WKWebview
- 空格
运营人员由于在通讯工具中复制粘贴,导致前面多了一个空格,没有仔细检查,直接录入了后台管理系统。
- 中文
运营人员为了方便自身统计,直接在url中加入中文,录入了后台管理系统。
现象均为打开一个空白页,常见的处理手段如下:
- 将参数里的中文URIEncode
- 去掉首尾空格
const safeUrl = (url: string) => {
const index = url.indexOf('?');
if (index === -1) return url.trim();
// 这行可以用任意解析参数方法替代,仅代表要拿到参数,不考虑兼容性的简单写法
const params = new URLSearchParams(url.substring(index));
const paramStr = Object.keys(params)
.map((key: string) => {
return `${key}=${encodeURIComponent(params[key])}`;
})
.join('&');
const formatUrl = url.substring(0, index + 1) + paramStr;
return formatUrl.trim();
};
可以看到虽然这里提出了一个 safeUrl
方法,但如果业务中大量使用 window.location.href
, window.location.replace
, 之类的方法进行跳转,替换起来会比较繁琐.
再比如在 Hybrid App
的场景中,虽然都是跳转,打开新的 webview
,还是在本页面跳转会是不同的实现,所以在业务内提取一个公共的跳转方法更有利于健壮性和拓展性。
值得注意的是,如果链接上的中文可能是用于统计的,在上报打点时,应该将其值(前端/服务端处理均可)进行 URIDecode
,否则运营人员会在后台看到一串串莫名其妙的 %XX
,会非常崩溃(别问我怎么知道的,可能只是伤害过太多运营)
2. 格式刺客
格式刺客指的是,不管何种原因,不知何种场景,就是不小心配错了,打错了,漏打了等。
比如:https://www.baidu.com
就被打成了 htps://www.baidu.com、www.baidu.com
等。
// 检查URL格式是否正确
function isValidUrl(url: string): boolean {
const urlPattern = new RegExp(
"^(https?:\/\/)?" + // 协议
"(([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})" + // 域名
"(:[0-9]{1,5})?" + // 端口号
"(\/.*)?$", // 路径
"i"
);
return urlPattern.test(url);
}
以上是一个很基础的判断,但是实际的应用场景中,有可能会需要填写相对路径,或者自定义的 scheme
,比如 wx://
,所以检验的宽松度可以自行把握。
在校验到 url
配置可能存在问题时,可以上报到 sentry
或者其他异常监控平台,这样就可以比用户上报客服更早的发现潜在问题,避免长时间的运营事故。
3. 异形刺客
这种刺客在视觉上让人无法察觉,只有在跳转后才会让人疑惑不已。他也是最近被产品同学发现的,以下是当时的现场截图:
一段平平无奇的文本,跟着一段链接,视觉上无任何异常。
经过对跳转后的地址进行分析,发现了前面居然有一个这样的字符%E2%80%8B
,好奇的在控制台中进行了尝试。
一个好家伙,这是什么,两个单引号吗?并不是,对比了很常用的 '%2B'
,单引号是自带的,那么我到底看到了什么,魔鬼嘛~
在进行了一番检索后知道了这种字符被称为零宽空格,他还有以下兄弟:
\u202b-\u202f
\ufeff
\u202a-\u202e
具体含义可以看看参考资料,这一类字符完全看不见,但是却对程序的运行产生了恶劣的影响。
可以使用这个语句去掉
str.replace(/[\u200b-\u200f\uFEFF\u202a-\u202e]/g, "");
刺客的妙用
头一天还被刺客气的瑟瑟发抖。第二天居然发现刺客的妙用。
场景:
产品要求在微信环境隐藏标题
我方前端工程师:
- 大手一挥,发功完毕,准备收工
document.title = '';
测试:
来看看,页面A标题隐藏不了
我方前端工程师:
啊?怎么回事,本地调试还是好的,发上去就不行了,为什么页面A不可以,另外一个页面B只是参数变了变就行。
架构师出手:
页面A包含了开放标签,导致设置空Title失效,空,猛然想起了刺客,快用起来!
function setTitle(title: string) {
if (title) {
document.title = title;
} else {
document.title = decodeURIComponent('%E2%80%8B');
}
}
果然有效,成功解决了一个疑难杂症,猜测是微信里有不允许设置标题为空的机制,会在某些标签存在的时候被触发。(以上场景在 Android
微信 Webview
中可复现)
小结
以上只是工作中碰到 url
异常的部分场景和处理方案,如果小伙伴们也有类似的经历,可以在评论区中分享,帮助大家避坑,感谢朋友们的阅读,笔芯~
参考资料:
什么零宽度字符,以及零宽度字符在JavaScript中的应用 - 掘金whosmeya
来源:juejin.cn/post/7225133152490094651