http请求跨域问题分析
个人认为可能涉及很多http的知识,本人才疏学浅不敢妄自揣测,只是做个笔记为了以后对比理解,从原生fetch说起吧,前提假设有个后端服务,我用express来模拟,如下:
var express = require('express');
var app = express();
app.get('/stduy-cors', (req, res) => {
res.status(200).json({
hello: true,
world: false
});
});
app.listen(5555);
上面是服务端代码,假设前端服务在3000端口,我们在上面的代码下可以这样调用:
fetch('http://localhost:5555/cors', {
mode: 'no-cors'
}).then(res => {
console.log(res.type); //opaque
// 此时无法转为json,因为这种type下无法读取响应内容
return res.json(); // 报错
});
注意你不能用js拿到响应内容,但是可以用谷歌浏览器控制台查看。
常见解决方案
- 做一层中间层,服务端调服务端是没有跨域的,可以用node或ngix做中间层转发,这种方案比较常见。
- 服务端修改响应头,客户端修改请求头。
var express = require('express');
var app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', 'http://your-ip:your-port');
next();
});
app.get('/stduy-cors', (req, res) => {
res.status(200).json({
hello: true,
world: false
});
});
app.listen(5555);
客户端如下调用接口:
fetch('http://localhost:5555/cors', {
mode: 'cors'
}).then(res => {
return res.json(); // 正确
}).then(res => {
console.log(res);
});
客户端传入mode: 'cors'
, 服务端加上Access-Control-Allow-Credentials
为true, 和Access-Control-Allow-Origin
为你的ip+端口, 后者不能为通配符*
, 想必这是处于安全策略, 暂时就写到这,后面再补。