前端跨域解决方案--代理
代理服务器监听本地请求,然后由代理服务器转发请求到目标服务器,因为服务端不存在同源策略,所以不存在跨域问题。
1. webpack-dev-server
项目如果有使用 webapck 的开发服务器,那么只需要配置一下代理(proxy)就可以轻松实现跨域,如下
```
devServer: {
contentBase: [
path.join(__dirname, '../public'),
path.join(__dirname, '..')
],
hot: true,
host: '0.0.0.0',
disableHostCheck: true,
// 代理相关
proxy: {
'/api/**': { // 匹配代理路径规则,仅代理接口请求,页面和静态资源请求不需要
target: 'http://test.com', // 后端提供的目标接口地址
pathRewrite: {'^/api': ''}, // 重写路径
secure: false, // 接受 运行在 https 上的服务
changeOrigin: true // 默认false,是否需要改变原始主机头为目标URL
}
}
}
```
2. node.js
http-proxy-middleware 中间件实际就是将 http-proxy 封装,使用起来更加方便简单。
```
const express = require('express');
const app = express();
const { createProxyMiddleware } = require('http-proxy-middleware');
const port = 8888; // 代理服务端口
app.use('/', createProxyMiddleware({
// 代理跨域目标接口
target: 'http://test.com',
changeOrigin: true,
// pathRewrite: {
// '^/api' : '/', // 重写请求
// },
// 修改响应头信息,实现跨域并允许带cookie
onProxyRes: function(proxyRes, req, res) {
const origin = req.headers.origin || '*' // 当前端只跨域不带cookie时,可为*
res.header('Access-Control-Allow-Origin', origin);
res.header('Access-Control-Allow-Credentials', 'true'); // 它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
}
}));
app.listen(port);
console.log(`Proxy server is listen at port ${port}...`);
```
3. nginx
1). 浏览器请求 nginx, 然后 nginx 代理去访问前端资源和后端接口,因为对于浏览器来说,接口和页面是同一个域名和端口,而服务端又不存在跨域,从而实现跨域访问。
#proxy 服务器 配置
server {
listen 8888;
server_name localhost;
location / {
proxy_pass http://localhost:8080; # 除localhost:8888/api/ 外的其他请求代理到 localhost:8080 (前端自己的服务)
}
location /api/ {
proxy_pass http://test.后端接口.com; # 将 localhost:8888/api/ * 请求代理到了http://test.后端接口.com; (后端接口服务器)
}
}
2). nginx 仅代理后端接口地址,设置为允许所有的 域请求或允许前端的域请求。实质和CORS跨域原理一样,通过配置文件设置请求响应头Access-Control-Allow-Origin...等字段。
#proxy 服务器 配置
server {
listen 8888;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /api/ { # 当请求为 localhost:8888/api/* 时, 代理转发到 http://test.后端接口.com/api/*
proxy_pass http://test.后端接口.com; # 后端目标服务器
add_header Access-Control-Allow-Origin http://localhost:8888; #当前端只跨域不带cookie时,可设置为 *
add_header Access-Control-Allow-Credentials true;
}
}
4. 猜想
看到这里,也许你的心里会有疑问,既然 nginx 可以有两种实现的思路,那么前面的 webpack 和 node.js 应该也可以做到啊,因为他们在这里都是作为代理服务器使用的啊?
恭喜你猜对了,答案是:可以的。
对于 node.js 和 webpack 的开发服务器,我们同样可以实现,既代理静态资源又代理后端接口的方案,简单说:就是让浏览器的所有请求都走代理服务器,根据不同的请求规则,由代理服务器去匹配对应的资源或接口。
比如,下面的 node.js 方案:
const express = require('express');
const app = express();
const { createProxyMiddleware } = require('http-proxy-middleware');
const port = 8888;
app.use('/html', createProxyMiddleware({ // 当浏览器访问 localhost:8888/html/ 时,匹配的是前端资源
target: 'http://0.0.0.0:8082', // 前端资源地址
changeOrigin: true,
pathRewrite: {
'^/html' : '/', // 重写请求
}
}));
app.use('/api', createProxyMiddleware({ // 当浏览器访问 localhost:8888/api/ 时,匹配的是接口地址
// 代理跨域目标接口
target: 'https://test.接口.com',
changeOrigin: true,
pathRewrite: {
'^/api' : '/', // 重写请求
},
// 修改响应头信息,实现跨域并允许带cookie
onProxyRes: function(proxyRes, req, res) {
const origin = req.headers.origin || '*'
res.header('Access-Control-Allow-Origin', origin);
res.header('Access-Control-Allow-Credentials', 'true');
}
}));
app.listen(port);
5.最后
总结: 相对来说,使用 webpack 来实现跨域的配置是最简单的、成本最低的一种解决方案,也是我平时开发中用的最多的,这里比较推荐。