We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ping-url是我最近开源的一个小工具,这篇文章也是专门写它设计理念的科普文。 为什么会做这个ping-url开源工具呢? 起因是:本小哥在某天接到一个特殊的需求,要用前端的方式判断任意一个url,是否可以正常访问。 这么简短的需求,通常背后都有个大坑:alien:
ping-url
先捊下思路,要实现这个功能,必须具备以下2点:
有了思路,就开始撸起袖子加油干!
由于浏览器的安全机制——同源策略的存在,要实现任意这个要求确实有点难。
任意
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
所以,为了实现任意url可以正常访问,第一个要解决的问题就是:跨域。
前端老鸟很快就会联想到JSONP。其原理其实是利用script可跨源访问的特性。 依据这个,可以做个拓展,找出所有可跨源访问的html标签:
JSONP
script
<script>
<img>
<link>
<video>
<audio>
<iframe>
从可跨源访问的html标签中,筛选出能支持onerror和onload事件标签,则可以依靠标签很好地完成功能的开发。 这里说明下:
onerror
onload
onerror事件的作用 如果跨源标签请求的资源,和本身能解析的文件格式不一样,就会报error事件。 而要检测的url,通常都是html。 所以onerror事件可以用于监听发起请求,到接收到反馈error所花费的时间。这样,就可以直接算出网络访问的延时。 但是,很遗憾,准确率并不是100%。 因为有一种情况是:url本身就是死链。 用死链发起http请求后,会得到failed的状态。这种情况下onerror也是会触发的。
error
html
failed
为什么需要onload事件? onload事件的触发时机是资源已下载完成。 只要触发这个事件,则证明url不是死链。 这样,就可以帮onerror排除意外情况,让准确率达到100%!
基于以上两点硬性要求,对标签进行过滤后如下:
其中<iframe>的硬伤是:只要服务器设置X-Frame-Options消息头,就直接废了。所以也被排除掉。
X-Frame-Options
X-Frame-Options是一个HTTP标头(header),用来告诉浏览器这个网页是否可以放在iFrame内。
<script>虽然可以满足需求,但是有一个很致命的问题:存在被XSS攻击的可能。 如果url对应的资源是可自执行的js函数,则完全有可能被利用干坏事。 <img>标签因为只能触发onerror,所以也被排除。
最后只有<link>标签可以使用。 由于解析方式是CSS,所以不存在攻击的可能性。 以下是实现代码:
function getStatus(url: string){ return new Promise((resolve, reject) => { let link = document.createElement('link'); link.rel="stylesheet"; link.type="text/css" link.href = url; link.onload = function(){ resolve(true); } link.onerror = function(){ resolve(false); } document.body.appendChild(link); }) }
url
body
需要注意的是,一定要声明rel和type,否则是触发不了绑定的事件的。
rel
type
由于CSS的跨域需要一个设置正确的Content-Type 消息头,所以还是存在很小概率的风险。 因此,计算网络延时这块,ping-url还是用最保守的<img>。
function getLoadTime(url: string){ return new Promise(resolve => { let img = document.createElement('img'); img.style.display = "none"; img.src=`${url}/?v=${Math.random()}`; const timeStart = new Date(); img.onerror = function(){ const timeEnd = new Date(); resolve(timeEnd.getTime() - timeStart.getTime()); } img.onload = function(){ const timeEnd = new Date(); resolve(timeEnd.getTime() - timeStart.getTime()); } document.body.appendChild(img); }); }
display:none
timeStart
这里有个小细节,url后要加上随机数v=***。这样可以避免缓存的情况。
v=***
虽然这只是个小项目,但是挺实用的。所以利用空闲时间,将其封装成npm包,发布到npmjs.com上。 源码也同步到GitHub上,可以点击访问ping-url。 如果对你有帮助的话,可以打赏个Star:star2:。
有个小遗憾:ping-url的测试覆盖率达不到100%,原因是:
async
await
__awaiter
__generator
有类似经验的码友,帮忙看下怎么解决,不盛感激!
[1] 华佗诊断分析系统 [2] 详解script标签 [3] 不要再问我跨域的问题了 [4] <link>:外部资源链接元素 [5] 跨源网络访问
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
ping-url
是我最近开源的一个小工具,这篇文章也是专门写它设计理念的科普文。为什么会做这个
ping-url
开源工具呢?起因是:本小哥在某天接到一个特殊的需求,要用前端的方式判断任意一个url,是否可以正常访问。
这么简短的需求,通常背后都有个大坑:alien:
先捊下思路,要实现这个功能,必须具备以下2点:
有了思路,就开始撸起袖子加油干!
一、判断url是否可访问
由于浏览器的安全机制——同源策略的存在,要实现
任意
这个要求确实有点难。所以,为了实现任意url可以正常访问,第一个要解决的问题就是:跨域。
1.1 解决同源限制
前端老鸟很快就会联想到
JSONP
。其原理其实是利用script
可跨源访问的特性。依据这个,可以做个拓展,找出所有可跨源访问的html标签:
<script>
<img>
<link>
<video>
<audio>
<audio>
<iframe>
1.2 如何判断访问性
从可跨源访问的html标签中,筛选出能支持
onerror
和onload
事件标签,则可以依靠标签很好地完成功能的开发。这里说明下:
onerror
事件的作用如果跨源标签请求的资源,和本身能解析的文件格式不一样,就会报
error
事件。而要检测的url,通常都是
html
。所以
onerror
事件可以用于监听发起请求,到接收到反馈error
所花费的时间。这样,就可以直接算出网络访问的延时。但是,很遗憾,准确率并不是100%。
因为有一种情况是:url本身就是死链。
用死链发起http请求后,会得到
failed
的状态。这种情况下onerror
也是会触发的。为什么需要
onload
事件?onload
事件的触发时机是资源已下载完成。只要触发这个事件,则证明url不是死链。
这样,就可以帮
onerror
排除意外情况,让准确率达到100%!基于以上两点硬性要求,对标签进行过滤后如下:
<script>
<img>
<link>
其中
<iframe>
的硬伤是:只要服务器设置X-Frame-Options
消息头,就直接废了。所以也被排除掉。1.3 存在的安全隐患
<script>
虽然可以满足需求,但是有一个很致命的问题:存在被XSS攻击的可能。如果url对应的资源是可自执行的js函数,则完全有可能被利用干坏事。
<img>
标签因为只能触发onerror
,所以也被排除。1.4 解析代码
最后只有
<link>
标签可以使用。由于解析方式是CSS,所以不存在攻击的可能性。
以下是实现代码:
<link>
节点,并加入资源地址url
onload
、onerror
body
中,发起请求需要注意的是,一定要声明
rel
和type
,否则是触发不了绑定的事件的。二、计算网络延时
由于CSS的跨域需要一个设置正确的Content-Type 消息头,所以还是存在很小概率的风险。
因此,计算网络延时这块,
ping-url
还是用最保守的<img>
。2.1 解析代码
<img>
节点,加入资源请求url,并将样式设置为display:none
,避免对页面产生影响timeStart
onerror
、onload
body
中,发起请求这里有个小细节,url后要加上随机数
v=***
。这样可以避免缓存的情况。三、开源共享
虽然这只是个小项目,但是挺实用的。所以利用空闲时间,将其封装成npm包,发布到npmjs.com上。
源码也同步到GitHub上,可以点击访问ping-url。
如果对你有帮助的话,可以打赏个Star:star2:。
求助
有个小遗憾:
ping-url
的测试覆盖率达不到100%,原因是:async
、await
__awaiter
、__generator
方法,测试用例无法覆盖所有路径有类似经验的码友,帮忙看下怎么解决,不盛感激!
参考
[1] 华佗诊断分析系统
[2] 详解script标签
[3] 不要再问我跨域的问题了
[4] <link>:外部资源链接元素
[5] 跨源网络访问
The text was updated successfully, but these errors were encountered: