关于node 中间层代理接口 使用stream 的方式转发接口,前端formdata传递的文件会丢失
**前提: **
- Node中间层服务是采用egg.js 开发,
- 会代理接口 ,对请求有些处理,在转发后端
- 想采用stream的方式对接口进行代理 场景 前端formdata上传文件,原采用方式是用egg封装的ctx.getFileStream获取文件流 写入buffer,再使用 superagent 的atach 使用buffer 上传给后端, 现准备采用类似 req.pipe(res) 的模式 进行请求 采用的request的流
ctx.body = request({ uri, method, ...requestOption.headers })
.on('response', response => {
Object.keys(response.headers).forEach((key) => {
// if ('content-length' === key) return;
if ('transfer-encoding' === key) return;
ctx.set(key, response.headers[key]);
});
})
.on('error', (error) => {
console.log(error)
})
.pipe(PassThrough())
但是发现转发后无法携带file文件流 后端无法获取到file 有没有一些好的方法解决代理 文件传输 或者 以上的方式可携带上文件流?
8 回复
我使用的axios,request类似,参考如下
app.use(async ctx => {
const options = {
url: 'http://localhost:3000', // 代理的地址
method: ctx.request.method,
headers: ctx.request.headers,
responseType: 'stream',
};
if (ctx.request.body && Object.keys(ctx.request.body).length) {
options.data = ctx.request.body;
} else {
// 上传文件,直接把ctx.req原生的req流传给data
options.data = ctx.req;
}
const result = await axios(options).catch(err => {
if (!err || !err.response) {
throw err || new Error('axios unknown error');
}
return err.response;
});
ctx.res.statusCode = result.status;
ctx.status = result.status;
await new Promise((resolve, reject) => {
for (const key in result.headers) {
ctx.set(key, result.headers[key]);
}
// axios返回的response数据注入到ctx.res
result.data.pipe(ctx.res);
result.data.on('end', () => {
return resolve();
});
result.data.on('error', err => {
return reject(err);
});
});
});
大佬, 现在有解决方案了吗?
楼主先搞明白 promise 和 callback 吧, koa 不支持 callback 的方式
代理不是你随便用一个 request 就可以搞定的,有很多坑需要填的,可以参考下 https://github.com/eggjs/egg-http-proxy 的源码
包一下就好了
await new Promise(function(resolve, reject){
// 逻辑自己包
request({ uri, method, ...requestOption.headers })
.on('response', response => {
Object.keys(response.headers).forEach((key) => {
// if ('content-length' === key) return;
if ('transfer-encoding' === key) return;
ctx.set(key, response.headers[key]);
});
})
.on('error', (error) => {
console.log(error)
})
.pipe(PassThrough())
})
@i5ting 代理没那么简单的,看我那个库里面那么多代码就知道了(即便如此,我那个库其实还有一些 edge case 没处理的)
就楼主的需求而言,可以直接用我那个库提供的 API
@atian25 嗯,他是request透传,还好,加中间人就麻烦了。你那个库确实更合适