eggjs 反向代理

上一篇文章讲了 umi 开启 ssr 然后使用 eggjs 进行渲染的相关内容。这篇文章趁热打铁,讲一下怎么使用 eggjs 反向代理。

正向代理和反向代理区别

先搞清楚正向代理和反向代理区别,这边以浏览器访问 www.google.com 为例

正向代理(forwar proxy): 比如有正向代理服务器 http://forward-proxy.com,客户端需要先设置浏览器代理服务器(一般浏览器或操作系统都支持代理服务器设置),然后在浏览器地址栏输入 www.google.com 进行访问。我们一般科学上网就是用这种配置。

反向代理(reverse proxy): 比如有反向代理服务器 http://reverse-proxy.com 代理了 www.google.com,那么客户端不用设置浏览器代理服务器,直接在浏览器地址栏输入 http://reverse-proxy.com,就会返回 www.google.com 的内容,在客户端看来,都不知道有 www.google.com 这服务

安装需要用到的插件

需要用到如下插件:

  1. koa2-connect
  2. http-proxy-middleware

安装插件

1
yarn add koa2-connect http-proxy-middleware

修改 router.js 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
'use strict';
// 导入需要用到的插件
const { createProxyMiddleware } = require('http-proxy-middleware');
const c2k = require('koa2-connect');

// 代理配置
const httpbinProxyOptions = {
target: 'https://httpbin.org', //要代理的地址
changeOrigin: true,
pathRewrite: {
'^/api': '', // 路径重写,后面我们会在 router 配置所有 /api 开头的请求都走该代理
},
};

// createProxyMiddleware 创建 express 类型的代理中间件,c2k 将 express 类型中间件转换成 koa2 类型中间件,eggjs 兼容 koa2 的中间件
const proxyMiddleware = c2k(createProxyMiddleware(httpbinProxyOptions));

/**
* @param {Egg.Application} app - egg application
*/
module.exports = (app) => {
const { router, controller } = app;
// router.all 是配置所有请求方法的规则,如果使用 router.get 那么只对 GET 请求进行处理。/api/* 表示所有 /api/ 开头的请求都使用 proxyMiddleware 中间件
router.all('/api/*', proxyMiddleware);
};

在 web 项目中使用

1
2
3
4
5
useEffect(() => {
fetch('/api/get?foo=bar').then((res) => {
console.log('res', res);
});
}, []);

在控制台看下打印,可以正常接收到请求,表示代理成功

重构

上面教程是在 router.js 里创建中间件,然后使用,这不是很符合 eggjs 的规范,现在进行重构,在 app/middleware 下创建反向代理中间件,原来 router.js 中相关代码可以删掉

1
2
3
4
5
6
7
//app/middleware/reverseProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
const c2k = require('koa2-connect');

module.exports = (options = {}) => {
return c2k(createProxyMiddleware(options.proxy));
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// config/config.default.js
module.exports = () => {
config.middleware = [ 'reverseProxy' ];
config.reverseProxy = {
match: '/api', // 当请求路径以此字符串开头时,使用该中间件
proxy: {
changeOrigin: true,
router: req => {
console.log('req.url', req.url);
// 可以根据请求的 url 返回不同的 target
return 'https://httpbin.org';
},
pathRewrite: {
'^/api': '',
}
}
}
}

现在 router.js 的代码干净了很多,代理配置移到了 config.default.js,后面修改起来也比较方便。

参考链接

How shall I use http-proxy-middleware in Koa2.0 ?