Skip to content

JSONP

JSONP是一种跨域共享资源的方法。

很多人会好奇JSONP和JSON是什么关系,JSONP是JSON with padding的缩写,即填充式JSON或参数式JSON,是被包含在函数调用中的JSON,如下面的样子:

js
callback({"name": "Chong"});

JSONP是通过动态<script>元素来实现的,使用时可以为src属性指定一个跨域URL。由于浏览器加载脚本是不受同源规则限制的,所以即使是跨域的URL同样可以发送请求。因为JSONP是有效的JavaScript代码,所以再请求完成后,即在JSONP响应加载到页面中以后,就会立即执行。

示例代码:

js
function handleResponse(response){
    alert("您的IP地址是 " + response.ip);
}

var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);

所以总结一下JSONP的实现方式:

  1. 向当前页面中动态插入一个<script>元素,src属性设置为请求地址,并在地址中指定好回调函数
  2. js代码中预先定义好jsonp的回调函数
  3. 请求完成后,会立即调用预先指定好的jsonp回调,并将数据以json的格式传递到回调中。

JSONP之所以可以实现跨域,依赖的是下面的条件:

  1. 浏览器请求脚本是不受同源规则限制的
  2. <script>元素加载完成的脚本会立即执行

需要注意的是,JSONP是需要服务端配合的,因为JSONP返回的是一段代码。

JSONP服务器端设置

js
//通过request事件来响应request请求
server.on('request',function(req, res){
    var urlPath = url.parse(req.url).pathname;
    var qs = querystring.parse(req.url.split('?')[1]);
    if(urlPath === '/jsonp' && qs.callback){
        res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'});
        var data = {
            "name": "Monkey"
        };
        data = JSON.stringify(data);
        var callback = qs.callback+'('+data+');';
        res.end(callback);
    }
    else{
        res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
        res.end('Hell World\n');    
    }    
});

注意点:

  1. jsonp 一般使用get,为防止浏览器缓存需要设置Cache-Control为no-cache
  2. 服务器端需要返回JSON格式的数据。

对比

优点:
  • 简单易用,浏览器支持好。
缺点:
  • JSONP是从其他域中加载代码并执行,所以存在很多安全隐患,如果其他服务器在响应中夹带恶意代码的话,没有办法防范。
  • JSONP难以确定请求失败的情况。HTML5中给<script>元素增加了一个onerror事件,但是还是有浏览器不支持。
  • 只能发送GET请求

问题

1. jsonp为什么不支持post方法

因为其使用的是script脚本的方式获取数据,其只能是get。