这是我的情况: 我想使用request库获取一些外部资源(二进制文件),并将其通过管道传输到我自己的应用程序的客户端。如果响应代码为!= 200或到达远程服务器时遇到问题,我想截取并提供自定义错误消息。理想情况下,如果响应很好,我希望保留原始标头。
我使用下面粘贴的第一段代码实现了这一目标。但是,我的整个应用程序都基于Promise API,因此我想使其保持一致并将其包装在promise中。当我这样做时,它不再起作用。首先,我尝试通过request-promise实现这一目标,但没有成功。然后,我尝试自己编写一个非常简单的示例,仍然没有运气。
工作示例
var r = request.get('http://foo.bar');
r.on('response', result => {
if (result.statusCode === 200) {
r.pipe(res);
} else {
res.status(500).send('custom error message')
}
});
r.on('error', error => res.status(500).send('custom error message');
无效的示例
var r;
return new Promise((resolve, reject) => {
r = request.get('http://foo.bar');
r.on('response', result => {
if (result.statusCode === 200) {
resolve();
} else {
reject()
}
});
r.on('error', reject);
}).then(() => {
r.pipe(res);
}).catch(() => {
res.status(500).json('custom error message');
});
“不工作”是指-没有响应,请求待处理,直到超时。
我已更改代码,以在传递给.pipe()
而不是resolve
的结果上调用r
。它响应客户端,但是响应为空。
最后,我尝试用简单的http.get()
替换请求库。这样,服务器将文件返回给客户端,但是缺少标头(例如Content-Type
或Content-Length
)。
我已经在Google上搜索了很多,尝试了多个请求版本...但没有任何效果。
答案 0 :(得分:3)
问题是,当触发"response"
时,您会创建一个立即解决的新Promise,但是then
回调始终是异步执行的,并且在调用它时,文件已到达服务器,并且不再有数据流通过该流。相反,您可以只使用回调的body
参数:
request.get('http://foo.bar', function(request, response, body) {
if(response.statusCode === 200) {
res.end(body);
} else {
res.status(500).end();
}
});
对于使用流request
似乎有点麻烦,axios
似乎做得更好:
axios.get("http://foo.bar"', {
validateStatus: status => status === 200,
responseType: "stream"
}).then(({data: stream}) => {
stream.pipe(res);
}).catch(error => {
res.status(500).json(error);
});