判断 URL 是否有效

在一个固有的环境中,需要让用户点击后台配置的不固定链接后,不非正常跳出固有业务系统,所以需要判断用户点击的 URL(内容)是否有效。那么如何判断一个 URL 是否有效呢?

背景

实体为终端机器,在 APP Webview 中加载 Web 单页面应用(SPA)。机器理论上可以24小时不间断工作(不关机),用户无法手动输入 URL。首页部分广告链接由后台管理,用户点击链接跳转相应页面。

问题

在用户点击链接(可能跨域)的时候,无效链接可能导致跳出业务系统,由于没有系统导航,则无法再返回原有业务系统,造成系统整体瘫痪。

定义

  • 有效链接:HTTP 请求 URL,相应内容可正常加载(一般为 200),此外均为不正常
  • 无效链接:HTTP 请求 URL,相应状态码以 4 或 5 开头的错误类型(如404),详细参考 HTTP 状态码

需求

在用户点击链接后,若是有效链接则执行正常路由跳转,否则友好提示错误原因,或者进行容错处理。

尝试解决

AJAX 请求

  • 同源:可通过 AJAX 返回状态来判断
  • 不同源:请求被浏览器阻止,返回 404,无法获取真实返回结果

JSONP 方式

JSONP 原理是采用动态添加 script 方式协同传输数据,因此需要服务器协助,返回约定格式数据,再作为脚本执行。

由于 URL 内容为 HTML 文档,不是 JSONP 格式数据,无法采用。

iframe 标签

iframe 标签本身就用于嵌入文档,而且支持跨域加载

可是问题来了,无法区分其加载内容结果状态,内容为 404 不存在时,其响应状态也为 200,都会触发 onload 事件,无 onerror 事件(暂有疑问)

不是办法的办法:通过查找内容文档的标题是否包含 404 等来判断结果

最终方案

<link> 标签

<link> 标签一般用于 CSS 样式表的加载,也可以可用于 预加载 使用(rel="prefetch"

1
<link rel="prefetch" href="http://foo.com" >

HTMLLinkElement 对象提供了 onloadonerror 事件,可分别对应加载成功和加载失败的事件处理

解决方案部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function checkValidURL (url, success, fail) {
const _lnk = document.createElement('link');
_lnk.rel = 'prefetch';
_lnk.as = 'document'; // Content type
_lnk.crossorigin = 'anonymous'; // CORS
_lnk.style.display = 'none';
_lnk.style.position = 'absolute';

_lnk.onload = function () {
_lnk.remove();
success && success(url);
};
_lnk.onerror = function () {
_lnk.remove();
fail && fail();
};

// Set target url
_lnk.href= url;

// Using body is valid too
document.body.appendChild(_lnk);
}

但是跨域 URL 可能依旧会有问题:

1
Refused to prefetch content from 'https://www.foo.com/xxx' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'prefetch-src' was not explicitly set, so 'default-src' is used as a fallback.

另见:Preloading content with rel="preload"

其他方案

服务器提供 API,前端传入 URL,后端进行判断,返回结果。

未完待续

若您有这个需求,或者对这个问题感兴趣,希望能参与交流

晓月风尘 wechat
扫描二维码与我相识
你我共同创造价值,记得支持一下哦~