koa2 请求转发实现
最近在学习vue3+nestjs,打算用这两个做一个博客(页面仔都喜欢做博客网站,我也一样!!)。为了节约时间,提高效率,博客网站的管理后台、数据统计页面我打算用之前做的基于vue2+kao2的项目。那么这样就出现了一个问题:后台管理页面有两个服务,一个是之前做好的基于koa2的,一个是基于新东西nestjs的。这样就需要做请求服务的代理将不同的服务代理到对应的服务器上。对于代理,有很多办法,前端
最近在学习vue3+nestjs,打算用这两个做一个博客(页面仔都喜欢做博客网站,我也一样!!)。为了节约时间,提高效率,博客网站的管理后台、数据统计页面我打算用之前做的基于vue2+kao2的项目。
那么这样就出现了一个问题:后台管理页面有两个服务,一个是之前做好的基于koa2的,一个是基于新东西nestjs的。这样就需要做请求服务的代理将不同的服务代理到对应的服务器上。
对于代理,有很多办法,前端配置代理,后端请求转发、网关处理等等。最后我选择了后端请求转发来处理。这样对原先的代码改动最少。
代码
直接上代码,屁话后面说
// 中间件 /middleware/httpProxy.js
const axios = require('axios');
const qs = require('qs');
module.exports = (opts = {}) => {
return (ctx, next) => {
if (!ctx.httpProxy) {
proxy(ctx, opts);
}
return next();
};
};
function proxy(ctx, opts) {
ctx.httpProxy = (params = {}) => {
params = Object.assign({}, { host: opts.apiHost || '' }, params);
let reqParams = Object.assign({}, params, formatReqParams(ctx, params));
if (reqParams.method.toUpperCase() !== 'GET') {
reqParams.data = params.data || ctx.request.body;
}
// application/x-www-form-urlencoded形式转发参数乱码修改
if (qs.stringify(ctx.request.body)) {
reqParams = { ...reqParams, data: qs.stringify(ctx.request.body) };
}
delete reqParams.headers.host;
return axios(reqParams)
.then(res => {
const { data, headers } = res;
setResCookies(ctx, headers);
return data;
})
.catch(err => {
// console.log(err)
return err;
});
};
}
function setResCookies(ctx, headers) {
const resCookies = headers['set-cookie'];
if (!headers || !resCookies || !resCookies.length || resCookies.length <= 0 || !resCookies[0]) {
return;
}
ctx.res._headers = ctx.res._headers || {};
ctx.res._headerNames = ctx.res._headerNames || {};
ctx.res._headers['set-cookie'] = ctx.res._headers['set-cookie'] || [];
ctx.res._headers['set-cookie'] =
ctx.res._headers['set-cookie'].concat && ctx.res._headers['set-cookie'].concat(resCookies);
ctx.res._headerNames['set-cookie'] = 'set-cookie';
}
/**
* @param {} ctx koa当前执行上下文
* @param {} params 请求参数
*/
function formatReqParams(ctx, params) {
let { url, method, headers, protocol } = ctx;
const { host } = params;
const hasProtocol = /(http|s):\/\//;
url = params.url || url;
method = params.method || method;
protocol = hasProtocol.test(url) ? url.split(':')[0] : params.protocol || protocol;
url = `${protocol}://${host}${url}`;
delete params.host;
return { url, method, protocol, headers };
}
// 注册及使用 app.js
const httpProxy = require('./middleware/httpProxy');
// apiHost即是你要转发请求到后端的host,其他的参数可以参考axioshttps://github.com/axios/axios
// 请求转发中间件,暂时只支持转发到另一个地址
// TODO: 支持多转发
app.use(
httpProxy({
apiHost: 'localhost:5000' // 全局端口
})
);
// 在需要使用的地方调用中间件
// http://xxx:4000/nest/xx的请求会转发到http://xxx:3000/nest/xx
if (url.startsWith('/nest')) {
const data = await ctx.httpProxy({
host: 'localhost:3000' // 多代理,nest地址代理到localhost:3000
});
// 这里可以做一些请求之后需要处理的事情
ctx.body = data;
}
使用说明及配置项
功能实现用到的依赖就一个axios,也没做别的魔改,所以配置参看axios
单转发
如果路由不做其他操作,只是简单的IP地址的转发
// 中间件注册
app.use(
httpProxy({
apiHost: 'localhost:5000' // 全局端口
})
);
// 使用
if (url.startsWith('/nest')) { // 路径匹配
const data = await ctx.httpProxy();
// 这里可以做一些请求之后需要处理的事情
ctx.body = data;
}
如果还有对接口地址进行修改的话
// 使用
if (url.startsWith('/test')) {
// 对url的处理
// 。。。
const data = await ctx.httpProxy({
// url: '/nest/schedule'
url: 'newUrl'
});
// 这里可以做一些请求之后需要处理的事情
ctx.body = data;
}
多转发
A转发newA,B转发newB。。。
// 中间件注册
app.use(httpProxy());
// 使用
if (url.startsWith('/nest')) {
const data = await ctx.httpProxy({
host: 'localhost:5000' // 多代理,nest地址代理到localhost:3000
});
// 这里可以做一些请求之后需要处理的事情
ctx.body = data;
} else if (url.startsWith('/test')) {
const data = await ctx.httpProxy({
host: 'localhost:3000', // 多代理,nest地址代理到localhost:3000
});
// 这里可以做一些请求之后需要处理的事情
ctx.body = data;
}
还有一个代理的中间件:http-proxy-middleware。但是看介绍好像只能在express里用,koa没有案例提示。
这样就可以在任何地方里转发请求,比如鉴权之后,或者是之前写好的项目的某个地方,从而实现服务的扩展。对原来的服务改动的也少。
效果
koa服务在本地的4000端口,nestjs服务在3000端口
直接访问3000端口:
访问4000端口,进行端口转发
修改url后再转发
不足
这只是简单的使用axios进行请求转发,不是真正的代理
这就导致会出现一些意想不到的错误,就比如传递body参数的时候由于不是xxx=xxx&xxx=xxx形式,所以第二次接收body参数会出现乱码,像下面这样:
等实在代码洁癖犯了想想换种实现方法
更多推荐
所有评论(0)