上节课我们简单介绍了如何通axios
发送请求,以及发送请求的跨域问题。从而引出了通过代理来解决跨域问题,但是我们也说了配置代理总共有两种方法,上节课是最简单的一种,那么这节课我们来讲另一种。
回顾
在开始讲新的这一种方法之前,我们来对上节课的内容来做一个简单的回顾。
react
本身只关注界面,不包含发送ajax
请求的代码- 前端通过
ajax
请求与后台交互(json
数据) react
应用中需要集成第三方ajax
库(或者自己封装)- 不推荐使用
jQuery
,推荐使用axios
- 通过配置代理解决跨域问题
- 代理端口一定要与客户端端口一致
以上便是上节课的主要内容,接下来我们来开始介绍第二种配置代理的方法。
配置需求场景
可能有人会觉得好奇了,我们上节课的那种方法不是挺好的嘛,有简单又有效,但是如果我们有多个代理要配置怎么办?
比如说这一个项目太大了,总共开了两个后端服务,这两个后端服务的端口肯定不一样啊,那么我们是不是要配置多个代理?那么上节课讲得第一种方法是不是就无法满足条件了?那么我们这节课要介绍的第二种方法变可以应对这种场景。
场景需求
现在我们有另一个测试接口,端口开在 5001,这个接口是用来获取车的信息。我们来看一下代码
export default class App extends Component { render() { return ( <div> <button onClick={this.getData}>Click</button> <button onClick={this.getCarData}>Click</button> </div> ); } getData = () => { axios.get("http://localhost:3000/students").then( response => {console.log("success",response.data);}, error => {console.log("error",error);} ) }; getCarData = () => { axios.get("http://localhost:3000/car").then( response => {console.log("success",response.data);}, error => {console.log("error",error);} ) }; }
现在我们组件中有两个按钮,第一个绑定onClick
事件并讲getData
方法作为事件回调,第二个按钮绑定onClick
事件,并用getCarData
方法作为事件回调,那么是不是就意味着我们点击第一个按钮,请求第一个在 5000 端口的接口,点击第二个按钮,对应的就去请求在 5001 端口的接口?那我们应该怎么配置呢?还是改package.json
?不可能啊,package.json
里面不可能出现两个proxy
字段啊,首先在json
语法上就不对了。那么我们应该怎么处理?
多代理配置
如果我们想要配置多个代理,我们就不能在package.json
里面配置了,我们把原来配置的先删掉。我们如果想要在脚手架中来配置多个代理的话,我们需要通过在src
中编写一个文件叫setupProxy.js
来完成配置,而且这个文件的名字绝对不允许修改,否则将不起任何作用,而且在该文件里面我们将不能使用ES6
语法。因为脚手架会自动找到这个文件并加到webpack
的配置中去,而webpack
使用的是node.js
里的语法,所以这个文件中得使用CJS
语法来编写。
那么我们来看一下:
const {createProxyMiddleware} = require('http-proxy-middleware'); module.exports = function (app) { app.use( createProxyMiddleware("/api1", { target: "http://localhost:5000", changeOrigin: true, pathRewrite: { "^api1": "" } }) ); }
首先我们来看一下代码,第一步引入http-proxy-middleware
中间件,这个中间件在外面创建项目的时候脚手架就自动帮我们安装好了,因为我们这里是CJS
语法所以不能再用import
了,然后我们要导出一个对象,但是现在新版要求我们写成一个函数,那么我们就写成函数吧,然后这个函数会接收到一个服务对象,我们用app
参数接一下。
然后在函数体内我们需要调用app
上的一个使用的方法,那么我们使用什么?我们既然要配代理那是不是就要使用代理啊使用使用createProxyMiddleware
,调用的时候要传两个参数,第一个就是我们的请求前缀,我们有多个服务器要请求,那么我得用一个前缀来标识那些请求对应哪个服务器啊。当我们写了前缀之后,就代表这以后所有包含这个前缀的请求都转发给我们指定的服务器。那么转发给谁呢?这就引出了我们的第二个参数。
第二个参数得接收一个配置对象。这个对象里面要有一个属性target
,我得指定这个请求转发给谁啊,然后下面一个属性changeOrigin
是什么意思?这个属性能够让服务器明确知道这个请求是从哪发送的,然后pathRewrite
,这个是什么?是不是url
路径改写?如果我们不写这个是不是连带着url
前缀一起就转发给服务器了?那么服务器中的接口url
有写这个前缀吗?这个前缀是我们自己写的,服务器压根就不知道这么个玩意儿。所以说如果不写pathRewrite
的话即便请求转发了那肯定会 404 的。那么这些事儿都做完是不是就可以发送请求了呢?我们来试一下。先重启脚手架,然后点击按钮请求接口:
是不是报错了?404 为什么 404?我们是不是没有改 App
组件中的url
?我们没有加前缀啊,没有加前缀的话就识别不出来有代理指定啊。所以我们来改一下App
组件:
export default class App extends Component { render() { return ( <div> <button onClick={this.getData}>Click</button> <button onClick={this.getCarData}>Click</button> </div> ); } getData = () => { axios.get("http://localhost:3000/api1/students").then( response => {console.log("success",response.data);}, error => {console.log("error",error);} ) }; getCarData = () => {...}; }
我们先改了getData
方法,因为我们目前只加了一个代理是转发到 5000 端口的,只有getData
是去 5000 端口拿数据的,那么我们来看一下这次是不是可以成功呢?
这次我们成功拿到了数据,那么现在我们是成功添加了一个代理,那么另一个代理怎么添加呢?再回到setupProxy.js
中,app.use
方法是可以接收很多个参数的,我们在加一个createProxyMiddleware
的调用就可以了啊。
const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function (app) { app.use( createProxyMiddleware("/api1", { target: "http://localhost:5000", changeOrigin: true, pathRewrite: { "^/api1": "" } }), createProxyMiddleware("/api2", { target: "http://localhost:5001", changeOrigin: true, pathRewrite: { "^/api2": "" } }) ); }
我们再看,我们两次调用createProxyMiddleware
是不是都没用什么区别,就是改了端口号和url
前缀,那么既然加了第二个代理,那么getCarData
方法中的url
是不是也要跟着改一下前缀,那么我们现在再看一下效果:
这一次我们两个按钮的请求是不是都成功拿到数据了。
setupProxy
的属性讲解
我们看一下我们之前写的这一部分:
createProxyMiddleware("/api1", { target: "http://localhost:5000", changeOrigin: true, pathRewrite: { "^/api1": "" } })
首先这些属性都是什么意思呢?
我们先看那个/api1
这个是什么?我们说了是url
前缀,那么是干什么的?我们开了代理,但是我们也不能什么都走代理吧,如果说我们要获取前端自身的东西,肯定就不会去走代理的,所以说这个url
前缀的用途就是控制哪些请求走代理。
在看看target
属性,这个就简单了,我代理是转发请求的,我得通过这个属性来告诉代理服务器把这个请求发给谁。
那么changeOrigin
属性又是什么呢?这个属性其实默认值是false
,但是我们要求尽量都改成true
,为什么?首先这个属性是用来控制服务器收到的请求头中Host
的值的。如果该属性为false
我们来看一下:
服务器知道这个请求是localhost:3000
发过来的,但是如果我们加了changeOrigin
属性,而且设为true
之后在请求会什么样子呢?
这一次不一样了,服务器获取到的host
就变成了localhost:5000
,所以说我们最好加上这个属性。
那么再来看pathRewrite
属性,如果我们不加这个属性的话会变成什么样子?我们之前是不是也说了会报 404?因为走代理会去服务器请求/api1/students
,但是服务器没有这个url
其实。那么我们来验证一下:
首先是不是 404 了?然后我们再看一下啊服务端:
是不是跟我们说的一样?我们是到服务器上去请求/api1/students
,但是服务器端并没有这个url
所以说就会报 404。
以上便是配置代理的第二个方法
总结
- 配置多个代理不能在
package.json
里面配置 - 在
src
中编写一个文件叫setupProxy.js
来完成配置多个代理 setupProxy.js
文件名固定不运行改setupProxy.js
文件得使用CJS
语法来编写- 用
url
前缀来指定请求走代理 target
属性来指定转发的服务器changeOrigin
属性尽量设为true
pathRewrite
属性是必须的,否则会报 404- 可以通过在
use
中多次调用createProxyMiddleware
来配置多个代理
Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.
Link of this article:https://work.lynchow.com/article/proxy_of_scaffold_2/