针对ajax跨域问题,nodejs解决方案
ajax跨域的原理
首先需要明确的是只有ajax请求才会出现跨域,像<script src>
这类请求,并不存在跨域问题。 ajax出现请求跨域错误问题,主要原因就是因为浏览器的“同源策略”,可以参考
CORS请求原理
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
基本上目前所有的浏览器都实现了CORS标准,其实目前几乎所有的浏览器ajax请求都是基于CORS机制的,只不过可能平时前端开发人员并不关心而已(所以说其实现在CORS解决方案主要是考虑后台该如何实现的问题)。
关于CORS,强烈推荐阅读 跨域资源共享 CORS 详解(阮一峰)
另外,这里也整理了一个实现原理图(简化版):
如何判断是否是简单请求?
浏览器将CORS请求分成两类: 简单请求 (simple request)和 非简单请求 (not-so-simple request)。 只要同时满足以下两大条件,就属于简单请求。
- 请求方法是以下三种方法之一:
HEAD
,GET
,POST
- HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type(只限于三个值application/x-www-form-urlencoded、 multipart/form-data、text/plain)
凡是不同时满足上面两个条件,就属于非简单请求。
如何解决ajax跨域
JSONP方式解决跨域问题
jsonp解决跨域问题是一个比较古老的方案(实际中不推荐使用),这里做简单介绍(实际项目中如果要使用JSONP,一般会使用JQ等对JSONP进行了封装的类库来进行ajax请求)
实现原理
JSONP之所以能够用来解决跨域方案,主要是因为 <script>
脚本拥有跨域能力,而JSONP正是利用这一点来实现。具体原理如图
实现流程
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) {
console.log('response data: ' + JSON.stringify(data));
};
请求时,接口地址是作为构建出的脚本标签的src的,这样,当脚本标签构建出来时,最终的src是接口返回的内容 浏览器返回
foo({
"test": "testData"
});
由于<script>
元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse的步骤。
实际应用 前端代码
$.ajax({
url: url,
method: 'get',
dataType: 'jsonp',
success: function () {}
);
node(express) 代码
express
只需要使用res
的jsonp
方法,将返回对象发给客户端即可。
app.use(PATH, (req, res) => {
var reponseData = {a: 'aaa'};
res.jsonp(responseData);
})
CORS解决跨域问题
Node.js后台配置(express框架)
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1')
//这段仅仅为了方便返回json而已
res.header("Content-Type", "application/json;charset=utf-8");
if(req.method == 'OPTIONS') {
//让options请求快速返回
res.sendStatus(200);
} else {
next();
}
});
前端代码
$.ajax({
url: url,
method: 'post',
success: function (res) {
console.log(res);
}
})
由于后端设置了cors设置,前端就可以像请求本地资源一样请求资源,非常方便。
总结
ajax 跨域问题,不推荐使用jsonp,而是后端服务做响应的配置,前端直接调用。
参考文档
https://segmentfault.com/a/1190000012469713