本地转发解决前端跨域
前言
在开发过程中, 遇到非自己人开发的后端接口, 时不时遇到跨域问题. 我们本着能动手不逼逼的原则, 自己本地启个服务转发一下, 绕开报跨域的浏览器大爷即可.
本文涉及安装依赖: node
, yarn
(npm
也行), Nginx
本文以本地3000端口请求百度为例, 在我的react demo页面请求一下百度
import React from 'react'
function App() {
const handleTestRequest = async () => {
try {
const res = await fetch('https://www.baidu.com')
console.log(res)
} catch (error) {
console.log('fetch error', error)
}
}
return (
<div className="App">
<button onClick={handleTestRequest}>fetch</button>
</div>
);
}
export default App;
结果, 毫无意外的报跨域错误.
解决方案:
独立的http-proxy-middleware来解决
它是一个npm库, 之前Marvin的Vue项目里见过面了, 可以很方便的帮助我们做请求转发, 先简单的非集成式的实现一下.
根据官方文档抄一下作业https://www.npmjs.com/package/http-proxy-middleware
- 安装
express
和http-proxy-middleware
yarn add express http-proxy-middleware
- 新建一个index.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use(
'/api',
createProxyMiddleware({
target: 'https://www.baidu.com/', // 需要跨域处理的请求地址
changeOrigin: true,
pathRewrite: { // 请求中去除/api
"^/api": ""
},
onProxyReq: function onProxyReq(proxyReq, req, res) {
// 我就打个log康康
console.log('--> ', req.method, req.baseUrl, '->', proxyReq.host + proxyReq.path);
}
})
)
app.listen(3001);
- 命令行启动一下
node index.js
这下我们已经有了一个本地3001端口的转发服务小帮手了, 所有发向http://localhost:3001/api
的请求, 小助手都会帮我处理一下后转发给百度.
- 代码改动试一下
fetch('http://localhost:3001/api')
- 不用上截图我就告诉你还是失败
因为
http://localhost:3000
向http://localhost:3001
的请求依然属于跨域, 他们还不是好朋友. 跨域的判定: 协议 + 域 + 端口 文档: https://developer.mozilla.org/zh-CN/docs/Glossary/Origin
下面让我们的3001
小助手认可3000
, 在们的index.js文件中, 添加onProxyRes等代码.
......
onProxyReq: function onProxyReq(proxyReq, req, res) {
console.log('--> ', req.method, req.baseUrl, '->', proxyReq.host + proxyReq.path);
},
onProxyRes: function onProxyReq(proxyRes, req, res) {
proxyRes.headers["Access-Control-Allow-Origin"] = "*"; // 或者直接写"http://localhost:3000"成为唯一好友
}
......
- 再请求试试. 肯定成功了, 自信回头不上图了
http-proxy-middleware 集成到 create-react-app
create-react-app
在react-scripts@0.2.3
之后对http-proxy-middleware
自带很好的集成
参考文档: https://create-react-app.dev/docs/proxying-api-requests-in-development
按照他的方式, 他会在我们启动的服务上(如我的localhost:3000
端口)直接集成转发, 省去我们手动启3001
, 以及让它和3000
成为好朋友的一步.
- 安装
yarn add http-proxy-middleware
- 在项目根目录src下新建setupProx.js文件 tips: 修改调试setupProxy.js文件需要重启服务
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'https://www.baidu.com',
changeOrigin: true,
pathRewrite: { // 请求中去除/api
"^/api": ""
},
onProxyReq: function onProxyReq(proxyReq, req, res) {
console.log('--> ', req.method, req.baseUrl, '->', proxyReq.host + proxyReq.path);
},
})
);
};
- 请求里尝试一下
try {
const res = await fetch('http://localhost:3000/api')
console.log(res)
} catch (error) {
console.log('fetch error', error)
}
}
- 肯定成功了, 自信回头.
Nginx转发
nginx各个平台的安装过程自己百度, 略
安装完了
nginx -t
一下, 查看一下nginx的配置文件位置, 直接去修改nginx.conf, 修改代码如下:
server {
listen 3001;
server_name localhost;
location / {
add_header Access-Control-Allow-Origin "*";
proxy_pass https://www.baidu.com;
}
}
启一个3001的服务, 负责转发, 同时也别忘了我们之前3000 -> 3001报跨域错误的问题, 记得添加一个header.
- 改完修改, nginx -s reload重启一下, 收工.