THE PROMISING LAND OF JSONP

Posted JavaScript与编程艺术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了THE PROMISING LAND OF JSONP相关的知识,希望对你有一定的参考价值。

当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 THE PROMISING LAND OF JSONP

PROMISE 極楽浄土的七宝楼阁

在 modern javascript 的“Pure Land”中 Promise 早已取代异步回调(callback hell),其趋势在 JavaScript 的婆娑世界中亦无可撼动。改革春风正在遍吹,例如在浏览器中,古老的 xhr 回调已被返回 Promise 的  fetch 解决;在服务端 Node.js 中,+8.0.0 之后的版本,util.promisify 已经开始对 fs 等其他模块的异步回调动手;来自 C# 的 async / await 更将此次 promisify 的战鼓擂的震天价响,“红旗招展,鞭炮齐鸣” 并非言过其实。正是由于 JavaScript 的不断换血和蜕化才使得其生态迸发勃勃生机,惹得万物萌动,春意盎然。

除了 Promise 的流行,将 jsonp promisify 我们还可以得到什么好处呢?promisify 后我们可以随意控制和组合 jsonp 这股原本“邪恶”的异步流,煎炸焖烹溜煨炖,红烧清蒸卤煮盐焗碳烤,拔丝蜜汁糖醋任君选,哦不,应该是串行、并行、Race、线性错误处理机制,一切 Promise 携带的好处我们都将享受到。Delicious & Cooooool!

WHAT IS JSONP

THE PROMISING LAND OF JSONP

以下解释摘自维基百科

JSONP (JSON with Padding or JSON-P) is used to request data from a server residing in a different domain than the client. It was proposed by Bob Ippolito in 2005.[2] JSONP enables sharing of data bypassing same-origin policy.

总而言之 JSONP 是一种获取跨域资源的方法。先介绍下跨域的基础知识:

你今天“跨域”了吗?

一、何谓“域”?

域即 origin,其定义为 “An origin is defined as a combination of URI scheme, host name, and port number”,即 origin 是 scheme、host name、port 的集合。公式表示为 origin = scheme "://" host [ ":" port ] 来自 rfc6454

举个 rfc 官网的例子 https://tools.ietf.org/html/rfc6454#section-4,则 scheme = httpshost = tools.ietf.orgport=443

二、何谓“跨域”?

跨域即 Cross Origin。先解释“同域”:“Two URIs are part of the same origin if they have the same scheme, host, and port”,scheme、host 和 port 三者都相同则同域,否则只要三者有其一不同,则称之为“跨域”。

三、为何限制“跨域”?

防止敏感信息比如 cookie 等被第三方窃取。

HOW JSONP WORKS

下面介绍下 jsonp 如何做到跨域获取资源。简单一句话有两点需解释。

一、为何 JSONP 可以”跨域“?

引用外部 JS 时,比如我们引入 jquery <script ></script>,该资源来自 https://cdn.bootcss.com,对于引用其的网址来说明显跨域了,但是为什么 jquery 还能正确执行呢,因为 script 天生就有跨域能力 ,jsonp 正是利用这一点达到跨域的能力。  

注意:不能在 HTTPS 网站内加载非 HTTPS 的资源。原因

网站支持 HTTPS 是保护您的网站和用户免受攻击的重要一步,但混合内容会使这种保护失效

—— 来自 Chrome

所以你没法在 HTTPS 网站中注入 src 来自 HTTP 的脚本,但并不表示,JSONP 不支持跨域,因为这仅是 HTTPS 的保护策略导致的。反过来我们可以在非 HTTP 网站注入 src 是 HTTPS 的脚本,所以从这一点来看,JSONP 支持跨域并不是一句夸大其词的 slogan。

THE PROMISING LAND OF JSONP


二、资源如何获取?

最重要的一点,跨域后资源如何获取?我们知道引入外部 JS 后,该 JS 会自动执行,且其执行环境和我们的 JS 处于同一个环境,即他可以执行我们自定义的全局函数。所以服务端只要和客户端协商好该函数,然后将 payload 即资源(通常是一个字面量对象),当做该函数的实参,当 JS 加载完毕,浏览器会自动执行该全局函数,而全局函数是我们自定义的,当然就能获取到该资源。

这个全局函数就是一个获取资源钩子,即 JSONP 中 P(Padding 或 Prefix,放在前面自然就是“前缀”)。注意 JSONP 中的 JSON,并非一定要是 JSON,因为只要能在 JS 环境中编译即可,即只要是一个有效的 JS 字面量即可。请注意:JSON 和 JS 的字面量对象是有区别的。

期中总结

JSONP 跨域必须施行以下两点,第一点:动态注入 script,第二点:协商的全局函数。

第一点是为了跨域,第二点是为了获取资源。看一个具体的例子来验证下我们的猜想。先验证第二点。

协商的全局函数

我们去优酷抓一个下拉提示的 JSONP 链接:http://tip.soku.com/search_tip_1?jsoncallback=XBox.dUpdate&query=向往的&site=14,将其在新窗口打开,观察其返回值。

THE PROMISING LAND OF JSONP


发现 jsoncallback 指向的 XBox.kUpdate 很有可能就是“全局函数”,即 JSONP 中的 P。验证方法:在 youku 控制台上输入window.XBox.kUpdate,发现确实存在该函数,输入 debug(window.XBox.kUpdate),然后修改输入框中的搜索词,发现浏览器 debugger 确实停在该函数内,则证实了第二点,有全局函数且资源下载完毕会执行该全局函数。

jsoncallback=XBox.kUpdate 改为 jsoncallback=whatever_func_you_like 试试,是不是返回值也变化了,说明该全局函数是“协商的”。

动态注入 script

youku 控制台输入 [...document.scripts].map(s => s.src).filter(src => src.startsWith('http://tip.soku.com')).length,修改搜索词,重新执行,发现长度加一,则验证了我们的第一点确实是通过动态注入 script 标签实现的。

理解这两点, 我们就可以写出一段通过 jsonp 获取跨域资源的代码了。而我们今天的目标就是将这段代码 promisify

function handleResponse(response) {  
 console.log('I got a response throught JSONP. Woow how awesome I am:', response);
}

var script = document.createElement("script");  
script.src = `http://tip.soku.com/search_tip_1?jsoncallback=handleResponse&query=向往的&site=14`;

document.querySelector('head').appendChild(script);

将上面代码复制粘贴到一个 HTTP 网站的控制台中执行,是否看到了最终效果?

THE PROMISING LAND OF JSONP

“刘郎已恨蓬山远 更隔蓬山一万重”

以上是关于THE PROMISING LAND OF JSONP的主要内容,如果未能解决你的问题,请参考以下文章

急!求Canada-land of the maple tree 课文

The Fintech 250: The Top Fintech Startups Of 2018

[论文阅读] (21)S&P21 Survivalism: Systematic Analysis of Windows Malware Living-Off-The-Land (经典离地攻击

Land of Farms HDU - 5556 二分图匹配

视频剪辑 Land of Dreams 航拍中国新疆篇 剪辑

hdu 5556 Land of Farms 最大团+暴力