[TOC]
请求不同源的数据即为跨域
什么是同源?
两个 URL 具有相同的协议,域和端口,则称它们是“同源”的。
以下的几个 URL 都是同源的:
但是下面这几个不是:
- http://**www.**site.com(另一个域:www. 影响)
- http://**site.org**(另一个域:.org 影响)
- https://site.com(另一个协议:https)
- http://site.com:**8080**(另一个端口:8080)
CORS
CORS是跨源资源共享(Cross-Origin Resource Sharing)
如果一个请求是跨源的,浏览器始终会向其添加 Origin
header
服务器可以检查 Origin
,如果同意接受这样的请求,就会在响应中添加一个特殊的 header Access-Control-Allow-Origin
。该 header 包含了允许的源或者一个星号 *
。然后响应成功,否则报错。
response.setHeader("Access-Control-Allow-Origin","http://xxx.com:9999")
JSONP
有的浏览器不支持CORS,比如IE9以前的版本
此时需要用到JSONP(JSON with padding)
其原理是使用script标签加载数据
在src中以参数形式将前端写好的回调函数传给后台调用,以返回需要的数据
假设我们要以这种方式从 http://another.com 网站获取数据,例如天气:
首先,我们先声明一个全局函数来接收数据,例如 gotWeather。
// 1. 声明处理天气数据的函数
function gotWeather({ temperature, humidity }) {
alert(`temperature: ${temperature}, humidity: ${humidity}`);
}
然后我们创建一个特性(attribute)为 src="http://another.com/weather.json?callback=gotWeather"
的 标签,使用我们的函数名作为它的 callback URL-参数。
let script = document.createElement('script');
script.src = `http://another.com/weather.json?callback=gotWeather`;
document.body.append(script);
远程服务器 another.com 动态生成一个脚本,该脚本调用 gotWeather(…),发送它想让我们接收的数据。
// 我们期望来自服务器的回答看起来像这样:
gotWeather({
temperature: 25,
humidity: 78
});
当远程脚本加载并执行时,gotWeather 函数将运行,并且因为它是我们的函数,我们就有了需要的数据。