node js 解决 CORS 跨域
一、本篇学前了解
-
那些情况不会有跨域?
ajax同源策略( 协议 主机(ip 域名) 端口相同)
同一个服务器下不会有跨域问题
服务器请求服务器没有跨域问题
-
什么是OPTIONS请求?
浏览器在某些请求中,在正式通信前会增加一次HTTP查询请求,称为"预检"请求(preflight)
览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。
只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错
(一般你看你请求一次会有2次network返回,其中一个请求方式就是OPTIONS)
-
toLowerCase() 方法用于把字符串转换为小写
-
以下配置都是在server.js中
二、解决跨域
1.利用中间件 cors
安装 npm i cors -S
使用方式一 : 为所有源启用跨域
const cors = require('cors')
app.use(cors())
app.listen(8000, function () {
console.log('start')
})
使用方式二 : 按条件配置
var express = require('express')
var cors = require('cors')
var app = express()
var whitelist = ['http://example1.com', 'http://example2.com']
// 异步配置
var corsOptions;
var corsOptionsDelegate = function (req, callback) {
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true} //在CORS响应中反映(启用)请求的起源
} else {
corsOptions = { origin: false} // 拦截请求
}
callback(null, corsOptions) // error options
}
app.all("*", cors(corsOptionsDelegate), function (req, res, next) {
if(corsOptions.origin === true){
if (req.method.toLowerCase() == 'options'){
res.sendStatus(200); //让options尝试请求快速结束
}
else{
next();
}
} else {
res.sendStatus(500); //被拦截
}
})
app.post('/cors',(req,res)=> {
res.send('ok')
})
app.listen(8000, function () {
console.log('start')
})
2.只使用路由的拦截实现
使用方式一 : 为所有源启用跨域
// 方式二 通过app路由的拦截
const express = require('express')
//express 实例化
const app = express()
// 所有请求都经过这里
app.all("*",function(req,res,next){
// 防止undefined 报错
if(!req.headers.origin){
return
}
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin","*");
// 例如 允许百度跨域, 把上面这行的*替换为 https://baidu.com
//允许的header类型
res.header("Access-Control-Allow-Headers","content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
if (req.method.toLowerCase() == 'options'){
res.sendStatus(200); //让options预验证尝试请求快速结束
}
else{
next();
}
})
app.post('/cors',(req,res)=> {
res.send('ok')
})
app.listen(8000, function () {
console.log('start')
})
使用方式二 : 按条件配置
// 允许多个跨域
const express = require('express')
//express 实例化
const app = express()
// 所有请求都经过这里
app.all("*",function(req,res,next){
var orginList=[
"http://www.bibi.com",
"http://www.qq.com",
"http://www.baidu.com"
]
// 防止undefined 报错
if(!req.headers.origin){
return
}
if(orginList.includes(req.headers.origin.toLowerCase())){
//允许的header类型
res.header("Access-Control-Allow-Headers", "content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin",req.headers.origin);
if (req.method.toLowerCase() == 'options'){
res.sendStatus(200); //让options尝试请求快速结束
}
else{
next();
}
} else {
res.sendStatus(500)
}
})
app.post('/cors',(req,res)=> {
res.send('ok')
})
app.listen(8000, function () {
console.log('start')
})
3.前端使用服务器代理
用node在本地搭建一个服务器, ajax请求自己搭建的node服务器
在node中请求 后端的服务器
安装 npm i request -S
const express = require('express')
//解析post消息体的插件
const request = require('request');
const bodyParser = require('body-parser')
//express 实例化
const app = express()
//使用中间件
//bodyParser.urlencoded 解析表单
app.use(bodyParser.urlencoded({
extended: false
}))
//解析json
app.use(bodyParser.json())
//自己的请求的接口
app.get('/cors',(req,res)=>{
//请求后端接口的地址
request('http://www.google.com', function (error, response, body) {
if(error){
console.log('error:', error);
} else {
console.log('body:', body);
res.send(body)
}
});
})
app.listen(8000, () => { //监听8000端口,开启服务
console.log('server start');
})