为什么要配置代理?

在React中,通常需要展示后端发送来的数据,前后端分离,下面是一个React请求后端发来的数据的例子

App.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from 'react'
import axios from 'axios'

export default class App extends Component {

getStudentsData = () => {
axios.get('http://localhost:5000/students').then(
response => {console.log("成功了",response.data)},
error => {console.log("失败了",error)}
)
}

render() {
return (
<div>
<button onClick={this.getStudentsData}>点击获取学生数据</button>
</div>
)
}
}

react 请求位于5000端口的服务器的学生数据,获取返回信息输出在控制台

开启客户端 npm start,在3000端口

server1.js

服务端代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const express = require('express')

const app = express()

app.use((req,res, next)=>{
console.log('server1接收请求')
next();
})

app.get('/students',(req,res)=>{
console.log('server1接收到请求')
res.json({ message: 'student数据' }); // 使用 JSON 格式返回数据
})

app.listen(5000, ()=>{
console.log('server1 running at http://127.0.0.1:5000')
})

服务端接收到来自客户端的请求后,会返回学生数据。

开启服务器,node server1.js,服务器端口监听5000端口。

当发送请求后,得到的结果如下图所示

报错Access-Control-Allow-Origin,发生跨域请求的错误。

基本原因是因为前端使用底层的ajax来发送请求,从3000端口转发到5000端口,服务端是可以接收到请求的,但是无法返回给前端。

所以我们需要配置代理,通过发送请求给代理,代理帮我们转发到服务器。代理发送的请求不是通过ajax 底层发送的,所以不会报跨域的错误。

配置代理方法1

如何正确配置代理,有两种方法。

其中一种方法是修改前端配置文件package.json

新增代理字段"proxy": "http://localhost:5000",表示代理接收到请求后转发到localhost:5000 的地址,即此处的服务端的地址

因为前端现在需要发送给代理,而不是直接发送给服务端,所以需要改变前端的请求url,应该发送给3000端口。

重新启动,并发送请求,得到结果如下,成功返回数据

但是在使用这种方法需注意,因为现在请求的是3000端口,即前端的端口,所以如果请求的数据地址是前端的静态资源地址,容易造成直接将前端的静态资源返回给浏览器,不通过代理。

配置代理方法2

在上一种方法中的服务端代码serve1.js的基础上,新增server2.js的代码

server2.js代码中,另开启一台服务器,开启在端口5001。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const express = require('express')

const app = express()

app.use((req,res, next)=>{
console.log('server2接收请求')
next();
})

app.get('/cars',(req,res)=>{
res.json({ message: 'car数据' }); // 使用 JSON 格式返回数据
})


app.listen(5001, ()=>{
console.log('server1 running at http://127.0.0.1:5001')
})

前端App.jsx新增另外一个请求按钮

1
2
3
4
5
6
7
getCarsData = () => {
// 获取车数据
axios.get('http://localhost:3000/cars').then(
response => {console.log("成功了",response.data)},
error => {console.log("失败了",error)}
)
}

此时会遇到一个问题,在package.json的配置文件中,我们只配置了一个代理,即所有发送给5000端口的数据都会经过这个代理转发。但是现在需要发送新的请求给5001端口,怎么办呢?

由于配置文件只能写一个代理,无法配置多个代理,所以我们使用方法2

src文件夹下新建一个setupProxy.js的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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': ''}
})
);
};

只有匹配到特定的api前缀才会转发数据,所以我们需要更改前端的url,

App.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
getStudentsData = () => {
axios.get('http://localhost:3000/api1/students').then(
response => {console.log("成功了",response.data)},
error => {console.log("失败了",error)}
)
}

getCarsData = () => {
// 获取车数据
axios.get('http://localhost:3000/api2/cars').then(
response => {console.log("成功了",response.data)},
error => {console.log("失败了",error)}
)
}

在服务端检查一下他的请求路径

server2.js

1
2
3
4
app.get('/cars',(req,res)=>{
res.json({ message: 'car数据' }); // 使用 JSON 格式返回数据
console.log("请求路径",req.url)
})

启动服务,发送请求,得到结果如下:

浏览器控制台:

服务器端:

成功输出路径,但是没有显示/api2,这是因为pathRewrite将/api2用空串替换