代理服務器監聽本地請求,然后由代理服務器轉發請求到目標服務器,因為服務端不存在同源策略,所以不存在跨域問題。
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 來實現跨域的配置是最簡單的、成本最低的一種解決方案,也是我平時開發中用的最多的,這里比較推薦。