【发布时间】:2019-07-11 00:05:05
【问题描述】:
我正在使用 node-mssql 模块从 express api 查询 SQL 服务器,并将行(带有一些中间步骤)传送到响应流。我想避免写入标头,直到我知道查询不会在任何行之前产生错误,这样我就可以向客户端发送有用的错误消息,而不是使用 express 默认处理程序终止流。但是,express 在某些时候会编写默认标头,我无法识别。
我已尝试在管道中的 .once('data',) 侦听器中编写标头,但此时某些默认行为已为我编写标头,这会产生错误。
let request = await new sql.Request(pool);
res.writeHead(200, {
'Transfer-Encoding': 'chunked',
'charset' : 'utf-8',
'Content-Type': 'application/json',
'Content-Encoding': 'gzip'
})
ndjsonStream.on('error', next)
request.pipe(ndjsonStream)
.pipe(transformer)
.pipe(gzip)
.pipe(res);
上述方法有效,但我无法传递有用的错误消息。
let request = await new sql.Request(pool);
ndjsonStream.once('data', () => {
res.writeHead(200, {
'Transfer-Encoding': 'chunked',
'charset' : 'utf-8',
'Content-Type': 'application/json',
'Content-Encoding': 'gzip'
})
})
ndjsonStream.on('error', next)
request.pipe(ndjsonStream)
.pipe(transformer)
.pipe(gzip)
.pipe(res);
request.query(query);
这会产生错误,因为 express 在此侦听器触发之前为我编写了一些标题,即 content-type: text/html。
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
【问题讨论】:
-
除非将所有内容缓冲到内存中,否则无法确保在响应开始流式传输到客户端后不会发生错误。流式传输期间随时可能发生错误。标头必须在响应正文之前发送,因此 express 可能会在开始写入响应数据时发送一些默认标头。您可以尝试使用
res.setHeader强制它使用某种内容类型,但在开始将数据传送到响应之前需要进行错误检测。
标签: node.js express chunked-encoding node-mssql