我有一个http服务器监听端口9090 -管道请求标准输出,像这样:
let server = http.createServer((req, res) => {req.pipe(process.stdout)})
server.listen(9090)
当我发送一些带curl的东西,像这样:
curl -XGET -T - 'http://localhost:9090' < /tmp/text-input
它工作了,我在服务器的终端上看到了输出
,但当我尝试以下节点:
const http = require('http')
const nurl = new URL("http://localhost:9090")
let request = http.request(nurl)
request.on('response', (res) => {
process.stdin.pipe(request)
})
request.end() // If I emit this, nothing happens. If I keep this, I get the below error
并尝试像这样运行它:node request.js < /tmp/text-input
,我得到以下错误:
node:events:368
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at new NodeError (node:internal/errors:371:5)
at write_ (node:_http_outgoing:748:11)
at ClientRequest.write (node:_http_outgoing:707:15)
at ClientRequest.<anonymous> (/home/tomk/workspace/js-playground/http.js:17:7)
at ClientRequest.emit (node:events:390:28)
at HTTPParser.parserOnIncomingClient (node:_http_client:623:27)
at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
at Socket.socketOnData (node:_http_client:487:22)
at Socket.emit (node:events:390:28)
at addChunk (node:internal/streams/readable:324:12)
Emitted 'error' event on ClientRequest instance at:
at emitErrorNt (node:_http_outgoing:726:9)
at processTicksAndRejections (node:internal/process/task_queues:84:21) {
code: 'ERR_STREAM_WRITE_AFTER_END'
}
我想管道我的stdin到http服务器相同的方式,我可以与curl -T -
。我的请求代码有什么问题?
简短回答
在node中发送分块编码消息,使用POST方法:
let request = http.request(url, { method: 'POST' })
process.stdin.pipe(request)
编辑:更直接的方法
或者,发送任何带有分块编码的请求方法:
let request = http.request(url)
request.setHeader("transfer-encoding", "chunked")
request.flushHeaders()
process.stdin.pipe(request)
稍长(但不完整)的答案
我打开了一个监听netcat(监听普通tcp),如nc -l 9090
,以查看curl
的请求如何与我的代码不同,并在头中发现了一些关键的差异。
在curl中,出现了标题Transfer-Encoding: chunked
,但在我的代码发出的请求中缺少。此外,我的代码有一个标题Connection: closed
我记录了请求对象,发现useChunkedEncodingByDefault
被设置为false
,这是令人困惑的从nodejs http文档的报价:
发送'Content-Length'报头将禁用默认的分块编码。
暗示它应该是默认值
但是后来我在节点
的源代码中发现了这个if (method === 'GET' ||
method === 'HEAD' ||
method === 'DELETE' ||
method === 'OPTIONS' ||
method === 'TRACE' ||
method === 'CONNECT') {
this.useChunkedEncodingByDefault = false;
} else {
this.useChunkedEncodingByDefault = true;
}
编辑
无论如何要发送分块编码,我(最终)发现我需要显式地添加Transfer-Encoding: Chunked
头:
request.setHeader("transfer-encoding", "chunked")
# and then
request.flushHeaders()
所以,综上所述,节点不允许发送发送默认GET请求与分块编码,但curl
。奇怪的是,不幸的是没有文档(据我所知),但重要的是我让它工作