本文详解基于 Node.js 的 JSONP 跨域请求实现。首先解析同源策略对 AJAX 的限制,阐述利用 script 标签 src 属性规避限制的原理。接着展示如何编写 Node 服务器解析 URL 和 QueryString 动态处理回调函数,并提供前端 HTML 及动态创建 script 元素的完整代码示例,帮助开发者掌握经典跨域解决方案。
JSONP 原理与同源策略限制
一、前言:
浏览器的安全机制核心在于同源策略。该策略要求资源访问必须满足三个条件一致:
1、协议相同;
2、域名相同;
3、端口相同。
然而,同源策略在保障安全的同时,也限制了 AJAX 进行跨域数据请求。为了突破这一限制,JSONP 成为一种常见的解决方案。
JSONP 的核心原理是利用 <script> 标签的 src 属性发起数据请求,该行为不受同源策略约束(<img> 和 <iframe> 的 src 同理)。服务器接收请求后,将数据封装在指定的回调函数名中返回给前端。
通过这种方式,即可实现跨域信息交互。
具体流程如下图所示:
理解 JSONP 的基本思路后,接下来我们将使用 Node.js 搭建一个简单的服务器,并配合前端代码,逐步完成一次完整的 JSONP 跨域请求实践。
Node.js 服务器搭建与路由处理
二、搭建 Node Server:
前端实现跨域请求需要后端配合。在此示例中,我们使用 Node.js 来模拟后台服务器环境。
因此,你需要具备基本的 Node.js 知识及开发环境。
下面开始编写一个简单的 Node 服务器。
首先,引入 http 模块以处理 HTTP 请求,并创建一个监听 8080 端口的 HTTP 服务器。
代码如下:
'use strict';
//通过require将http库包含到程序中
var http = require('http');
//创建新的HTTP服务器
var server = http.createServer();
//通过request事件来响应request请求
server.on('request',function(req, res){
res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
res.end('Hell World\n');
});
//监听8080端口
server.listen('8080');
//用于提示我们服务器启动成功
console.log('Server running!');
接着,为了区分 JSONP 请求与普通请求,服务器需要解析 URL 字符串。此处假设通过路径名 '/jsonp' 来识别 JSONP 请求。
代码如下:
'use strict';
//通过require将http库包含到程序中
var http = require('http');
//引入url模块解析url字符串
var url = require('url');
//创建新的HTTP服务器
var server = http.createServer();
//通过request事件来响应request请求
server.on('request',function(req, res){
var urlPath = url.parse(req.url).pathname;
//如果urlPath为'jsonp',就认定该请求为携带jsonp方法的http请求
if(urlPath === '/jsonp'){
res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'});
var data = {
"name": "Monkey"
};
data = JSON.stringify(data);
//假设我们定义的回调函数名为test
var callback = 'test'+'('+data+');';
res.end(callback);
}
else{
res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
res.end('Hell World\n');
}
});
//监听8080端口
server.listen('8080');
//用于提示我们服务器启动成功
console.log('Server running!');
上述代码第 19 行存在一个缺陷:回调函数名被硬编码。当判断为 JSONP 请求时,只能向前端传入固定的 'test',这显然不够灵活。
因此,我们需要引入 querystring 模块来处理查询字符串。
代码如下:
'use strict';
//通过require将http库包含到程序中
var http = require('http');
//引入url模块解析url字符串
var url = require('url');
//引入querystring模块处理query字符串
var querystring = require('querystring');
//创建新的HTTP服务器
var server = http.createServer();
//通过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');
}
});
//监听8080端口
server.listen('8080');
//用于提示我们服务器启动成功
console.log('Server running!');
至此,我们搭建好了所需的服务器。
服务器就绪后,接下来进行前端的跨域请求实现。
前端 JSONP 请求实现与动态脚本
三、JSONP 跨域请求之旅:
由于利用 <script> 标签的 src 发起请求,服务器约定在请求路径后添加 '/jsonp?callback' 即视为 JSONP 请求,且 callback 参数需携带前端已定义的全局方法名。
前端代码示例如下:
<!DOCTYPE html>
<head>
<title>jsonp</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<script>
function test(data){
alert(data.name);
};
</script>
<script src="http://127.0.0.1:8080/jsonp?callback=test"></script>
</body>
</html>
前后端代码编写完毕后,我们来验证效果。
首先启动 Node 服务器,命令如下:

注:示例中将服务器文件 server.js 存放于 D:/JSONP 目录。
随后运行上述 HTML 代码,可见请求成功并执行了 test 方法。
然而,页面加载即发起跨域请求可能并非最佳体验。我们可以动态创建 script 元素并指定请求,从而更灵活地控制时机。
代码如下:
//动态创建script标签,并请求
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.src = src;
document.body.appendChild(script);
};
//如:在onload后,跨域请求
window.onload = function(){
addScriptTag('http://127.0.0.1:8080/jsonp?callback=monkey');
};
//回调的方法,且必须为全局方法,不然会报错
function monkey(data){
alert(data);
};
使用 JSONP 时需注意,回调函数必须是全局方法,否则会因为 script src 请求成功后立即执行而报错。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。