NodeJS如何将标准输入流管道传输到HTTP请求,代码报错如何解决
问题原因
你的代码存在3个核心逻辑错误:
- 流写入的时机完全错误:HTTP请求的执行顺序是先发送完整请求(包含请求头+请求体),服务端处理后才会返回响应。你把
process.stdin.pipe(request)写在了response事件回调里,等到服务端返回响应时,请求的发送链路已经关闭,此时再往请求流写数据必然失败。 - 手动提前调用了
request.end():request.end()的作用是结束当前请求的写入流,标记请求内容发送完成。你在创建请求后直接调用该方法,等于刚创建请求就直接关闭了写入通道,后续触发pipe写入时就会抛出ERR_STREAM_WRITE_AFTER_END错误。如果注释该方法,请求会因为始终没有标记结束,服务端收不到完整请求而一直挂起,不会返回任何响应。 - 缺少必要的错误监听:请求流没有绑定error事件回调,出现错误时会直接抛出未捕获异常导致进程崩溃。
小提示:HTTP协议规范没有禁止GET请求携带请求体,但部分代理、服务端实现会忽略GET请求的请求体,如果你只是需要上传内容到服务端,建议将method改为
PUT或POST,兼容性更好。
正确实现代码
const http = require('http') const nurl = new URL("http://localhost:9090") // 如需和你curl命令的GET方法行为一致可保留method配置,传请求体更规范的方案是改用POST/PUT const request = http.request(nurl, { method: 'GET' }) // 错误处理 request.on('error', err => { console.error('请求异常:', err) }) // 响应处理逻辑 request.on('response', res => { console.log('服务端响应状态码:', res.statusCode) // 如需读取服务端返回内容可在此处处理res流 }) // 将标准输入直接管道到请求流,pipe会在stdin读取完成后自动调用request.end(),无需手动调用 process.stdin.pipe(request)
运行node request.js < /tmp/text-input即可实现和curl -XGET -T - 'http://localhost:9090' < /tmp/text-input完全一致的效果,服务端可以正常输出收到的请求体内容。
内容的提问来源于stack exchange,提问作者Tom Klino
相关产品推荐
相关产品推荐

