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. 异形刺客

这种刺客在视觉上让人无法察觉,只有在跳转后才会让人疑惑不已。他也是最近被产品同学发现的,以下是当时的现场截图:

URL刺客现身,竟另有妙用!

一段平平无奇的文本,跟着一段链接,视觉上无任何异常。

一开始我以为是产品最开始配置错误,后续配置没生效,所以我自信的打开了 chromenetwork ,发现 url 没有任何问题。

经过对跳转后的地址进行分析,发现了前面居然有一个这样的字符 decodeURIComponent('%E2%80%8B'),好奇的在控制台中进行了尝试。

URL刺客现身,竟另有妙用!

URL刺客现身,竟另有妙用!

一个好家伙,这是什么,两个单引号吗?并不是,对比了很常用的 '%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 异常的部分场景和处理方案,如果小伙伴们也有类似的经历,可以在评论区中分享,帮助大家避坑,感谢朋友们的阅读,笔芯~

参考资料:

零宽字符 – 掘金LvLin

什么零宽度字符,以及零宽度字符在JavaScript中的应用 – 掘金whosmeya

原文链接:https://juejin.cn/post/7225133152490094651 作者:windyrain

(0)
上一篇 2023年4月24日 上午10:41
下一篇 2023年4月24日 上午10:51

相关推荐

发表回复

登录后才能评论