我们的网站每天都会安排进行功能检查,对于关键性的页面,还会进行全页面的链接可用性扫描。之前一直用的是 Google 浏览器上Check My Links
这个扩展插件,总体来说速度还是很快的。
但是随着我们网站的安全升级,对于它高频触发的请求,我们会进行拦截重定向到锁定页面。然而由于是重定向,它识别不出来这个链接是否有问题,会被当成正常可用。
因此检测结果已经不能作为我们的测试依据,有必要对它进行改造。
Check My Links
插件(失败方案)实际业务中,我们服务端实际上是约定过特定 ip+ 请求 UA 的白名单机制,而且这个插件项目是开源的,于是一开始便打算对这个插件进行适应的改造。
然而分析了它源码、进行改造调试后发现,它的核心方法里,实际上是忽略了XMLHTTPRequest
请求出错的情况。而且谷歌浏览器上的遵循的 W3C 要求,请求 UA 不让修改的。
Check My Links
里面用了很多 chrome 特有的 Api,所以这一步我并没有直接把它迁移到 Firefox,而是二次改造 Firefox 上的Simple Link Checker
这个插件,并结合我们自身的需求进行了更为深度的功能定制。
迁移到 firefox 也是因为这个关键性的参数
setRequestHeader
在 chrome 不被允许修改请求 UA,而 firefox 的协议是可以的。var XMLHttpTimeout, client = new XMLHttpRequest(); client.open('GET', url, true); const brower_UA = navigator.userAgent; const custom_UA = `${brower_UA} Test-Header-XXX` client.setRequestHeader("user-agent", custom_UA); client.send();
var links = document.getElementsByTagName("a");
function sendMessagePromise(url) {
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({
"action": "check",
"url": url,
}, function(response) {
resolve(response);
});
});
}
async function linkCheck() {
for (let i=0; i<filterLinks.length; i++){
const ele = filterLinks[i]
const url = ele.href;
await sendMessagePromise(url)
.then(response => {
doSomething(response)
}
}
}
在原来的 chrome 插件里,对于请求失败的访问,默认 statusCode 为 0,虽然这是比较小概率的出现的,但是这样强制改写结果为通过,肯定是不合理的。
因此我这里是增加了对XMLHttpRequest.onError
的异常捕获,并封装了可参数化调用的重试方法,默认 5 次还不成功会抛出错误。
function check(url, retryCount = 5) {
var XMLHttpTimeout, client = new XMLHttpRequest();
...
client.onerror = function(e) {
if (retryCount <= 0) {
resolve({
status: 400,
message: url,
});
}else {
check(url, --retryCount)
}
};
}
对于报错的元素位置,之前工具只会是以红色背景色展示,对于我们整体主色调本身就是红色的网站来说,很不友好,有时还找不到。
因此本次我们对于报错的位置,结合 CSS 动画,进行了闪动处理,帮助检测人员快速定位到异常发生的位置。
@keyframes fade {
from {
opacity:1.0;
}
50% {
opacity:0.4;
}
to {
opacity:1.0;
}
}@-webkit-keyframes fade {
from {
opacity:1.0;
}
50% {
opacity:0.4;
}
to {
opacity:1.0;
}
}
.Fail {
border-radius:2px;
border-color:#c0392b;
color:#fff!important;
background-color:#c0392b!important;
animation:fade 600ms infinite;
-webkit-animation:fade 600ms infinite;
}
这个定制化插件,现阶段仅作为之前 chrome 的插件的替代升级工具。但长远的看,我们还可以结合业务做更多的扩展功能,看后期的使用发展和需求吧。