koa: Can't pipe stream to ctx.res
I’m trying to pipe streams to my response but it seems didn’t work
Simple test case:
const Koa = require('koa');
const app = new Koa();
const Router = require('koa-better-router');
const router = Router().loadMethods();
const request = require('request');
app.use(async (ctx, next) => {
const start = new Date();
await next();
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});
router.get('/', async (ctx) => {
ctx.req.pipe(request(`https://www.google.com/?q=${ctx.query.q}`)).pipe(ctx.res);
});
app.use(router.middleware());
app.listen(3000, () => {
console.log('listening on port 3000');
});
An error occurred:
$ node index.js
listening on port 3000
GET / - 35ms
internal/streams/legacy.js:59
throw er; // Unhandled stream error in pipe.
^
Error: write after end
at ServerResponse.write (_http_outgoing.js:450:15)
at Request.ondata (internal/streams/legacy.js:16:26)
at emitOne (events.js:96:13)
at Request.emit (events.js:189:7)
at IncomingMessage.<anonymous> (/Users/knowlet/test/node_modules/request/request.js:1088:12)
at emitOne (events.js:96:13)
at IncomingMessage.emit (events.js:189:7)
at IncomingMessage.Readable.read (_stream_readable.js:381:10)
at flow (_stream_readable.js:761:34)
at resume_ (_stream_readable.js:743:3)
And req.pipe(request(...)).pipe(res) works in express.js, I’m wondering is there anything I do wrong?
$ node -v
v7.6.0
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 18 (4 by maintainers)
You’ll want to let Koa handle the stream:
Oh, you have that. Ok, that will do.
How about this
ctx.body = request(`https://www.google.com/?q=${ctx.query.q}`);will also work.@catamphetamine Koa can be seen as a wrapper around the Node.JS HTTP APIs. Using those APIs directly bypasses Koa. Writing to Node.JS HTTP objects managed by Koa is likely to conflict with Koa, as it does in this case. If you don’t want Koa to touch the response, you can use
ctx.respond = false, which also makes OP’s example work perfectly. However, that is not the recommended solution, and it may cause problems with other middleware.That should work, as Koa checks
ctx.res.writable. You could also use the combined-stream package. Create a combined stream, append the header and footer, and then setctx.bodyto the combined stream.ERR_STREAM_CANNOT_PIPE
koajs@2.13.1 nodejs@12.18.3
For anyone using node-fetch. This seems to work:
@saxofficial Try
multistreamIt works as part of
react-isomorphic-render.