
背景
前端react
项目中使用fetch
请求nodejs
层服务器(使用express
),nodejs
层将请求进行处理,使用原生http
模块的request
方法转发,将返回的json
数据处理再返回给前端。
需求
将前端请求直接转发至后台,nodejs
层只处理多个接口的串/并行操作
方法
使用 node-http-proxy 第三方库将请求直接转发至后台
问题
这个模块不支持修改返回的数据,即原生res
对象中存储的后台返回数据。
解决方法
在node-http-proxy
的proxyRes
事件中重写原生res
的writeHead
和end
方法。
代码
const httpProxy = require('http-proxy');
const proxyOptions = {}; // your options here
const apiProxy = httpProxy.createProxyServer(proxyOptions);
apiProxy.on('proxyRes', (proxyRes, req, res) => {
const oriWriteHead = res.writeHead;
const oriWrite = res.write;
const oriEnd = res.end;
let jsonString = '';
Object.assign(res, {
writeHead: () => {},
write: (chunk) => {
jsonString += chunk.toString();
},
end: () => {
const oriJSONRes = JSON.parse(jsonString);
const handledJSONRes = fn(oriJSONRes);
const buffer = new Buffer(JSON.stringify(handledJSONRes)); // 一定要转成buffer,buffer长度和string长度不一样
const headers = Object.keys(proxyRes.headers)
.reduce((prev, curr) => {
const value = key === 'content-length' ? buffer.length : proxyRes.headers[key];
return Object.assign({}, prev, { [key]: value });
}, {});
oriWriteHead.apply(res, [statusCode, headers]);
oriWrite.call(res, buffer);
oriEnd.call(res);
}
});
});
-
fn
为你自己的处理函数,参数为原API
返回的JSON
数据对象 - 很重要的一点是将返回头的
Content-Length
重新赋值为你处理之后数据的长度,不然你会接受到Bad string
的错误。因为原返回头的Content-Lenght
为处理之前的数据长度
网友评论