下面我以简单的两台node服务器来讲明如何使用nginx进行前端跨域访问。html
const app = express();
app.get('/web/users',(req, res)=>{
res.json([{name:"张三",age:12},{name:"李四",age:14}]);
res.end()
})
app.listen(process.env.PORT || 8083);
复制代码
同域下的前端代码只需调用前端
function getUsers() {
var xhr=new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8083/web/users');
xhr.send(null);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}else {
alert(xhr.statusText);
}
}
}
复制代码
这里有一点须要关注的是,先后端代码处在同一个域下,xhr.open() url路径写成下面这样也是能够的,它会默认请求到http://localhost:8083/web/usersnode
xhr.open('GET', '/web/users');
复制代码
下面咱们将node1服务器中的web/users接口删除:nginx
const app = express();
app.listen(process.env.PORT || 8083);
复制代码
前端此时天然没法访问后台的web/users了,将报一个404错误。web
下面增长一个node2服务器,在localhost:8085上启动,同时咱们将原先在8083上删除的web/users接口搬迁到8085上:ajax
const app = express();
app.get('/web/users',(req, res)=>{
res.json([{name:"张三",age:12},{name:"李四",age:14}]);
res.end()
})
app.listen(process.env.PORT || 8085);
复制代码
因为8085实现了这个接口,咱们尝试在原先8083端口下的ajax调用它试试:express
xhr.open('GET', 'http://localhost:8085/web/users');
复制代码
如咱们所料,浏览器阻止了这次行为,并抛出一个跨域错误。 npm
难道就没法访问那个接口了吗?其实服务器之间和服务器之间是能够相互调用的,阻止跨域访问只是在浏览器端作的限制而已。json
下面我经过两种方式来实现如何访问到8085上的web/users接口。后端
原理就是交由8083后端去访问8085端口接口,访问完成交给前端
8083node后端实现代码:
npm install request --save // 须要安装一个http request模块
复制代码
const app = express()
const request = require('request')
// 访问此接口时经过request模块去访问8085 再返回给前端。
app.get('/web/users',(req, res)=>{
var url='http://localhost:8085'+req.url
console.log(url) // http://localhost:8085/web/users
req.pipe(request(url)).pipe(res);
})
复制代码
就是经过script 的src,向服务器请求数据,且这不受同源策略限制;而后服务器将相应的数据放入指定的函数回调名中,返回给前端。说的有点绕,下面经过实例讲解: 8083前端请求8085,这里已经再也不是ajax请求了,而是直接加载8085上资源。
<script>
function getUsers(data) {
alert(data)
}
</script>
<script src="http://localhost:8085/jsonp?callback=getUsers"></script>
复制代码
上述代码第一个script标签订义了一个函数getUsers 可是并无执行,只是定义了而已,要想有执行能力,须要
getUsers(data)
复制代码
因此咱们要让第二个标签script src="http://localhost:8085/jsonp?callback=getUsers" 返回getUsers(data)内容便可,这样第一个标签内定义的函数就能够执行了。返回接口内容只须要放到函数参数里便可
后台8085实现:
const app = express();
const querystring=require('querystring')
const url=require('url')
// 处理前端jsonp请求
app.get('/jsonp',(req,res)=>{
var qs = querystring.parse(req.url.split('?')[1]); //{callback:'getUsers'}
var users=JSON.stringify([{name:"张三",age:12},{name:"李四",age:14}]) // 注意须要传成字符串格式
var callback=`${qs.callback}(${users})`
res.end(callback)
})
复制代码
前端返回
是否是有点黑魔法的味道!可是缺点也是明显的,首先经过此方式有必定安全性的,经过callback后加一些乱七八糟的东西可能会有xss攻击,最主要的是jsonp不支持post方法。
此方式即相似于第一种node代理方式,也是经过服务器和服务器之间通讯,只是不须要8083下后台服务器本身去访问8085,而是专门交给nginx,为何?姑且认为nginx更加专业吧! nginx配置
server {
listen 8007; # nginx启动端口,须要访问这个端口才可以代理
server_name localhost:8083; # 须要代理的服务器
location / { # 若是你访问127.0.0.1/8002/的话nginx去请求
proxy_pass http://localhost:8083;
}
location /web { #访问/web/aa时会映射成http://localhost:8085/web/aa;
proxy_pass http://localhost:8085;
}
}
复制代码
8083请求路径
xhr.open('GET', '/web/users');
复制代码
CORS全称是跨域资源共享 是一个W3C标准,它规定浏览器容许发送ajax到不一样域下的服务器来获取数据,从而克服了原来限制,使用CORS须要先后端都支持,现代浏览器基本上都支持。具体CORS的知识能够参考阮一峰博客 www.ruanyifeng.com/blog/2016/0…
app.use('*',function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*'); //这个表示任意域名均可以访问,这样写不能携带cookie了。
//res.header('Access-Control-Allow-Origin', 'http://www.baidu.com'); //这样写,只有www.baidu.com 能够访问。
res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');//设置方法
if (req.method == 'OPTIONS') {
res.send(200);
}
else {
next();
}
});
复制代码
或者使用现成的CORS模块
npm install cors
复制代码
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://www.baidu.com',
optionsSuccessStatus: 200
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: '只有百度能够访问'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
复制代码
若有不正确,请指正^_^