Closed knowlet closed 7 years ago
You'll want to let Koa handle the stream:
ctx.body = ctx.req.pipe(request(`https://www.google.com/?q=${ctx.query.q}`));
It works, thanks for answering.
ctx.body = request(`https://www.google.com/?q=${ctx.query.q}`);
will also work.
I think OP might have wanted to stream the request and response (so POST data would be forwarded).
@PlasmaPower
You'll want to let Koa handle the stream:
Why?
What for?
ctx.res
is a standard HTTP response object so there shouldn't be any need for anything else
@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.
you can use
ctx.respond = false
Oh, you have that. Ok, that will do.
However, that is not the recommended solution, and it may cause problems with other middleware.
How about this
.use(async (ctx) =>
{
// https://medium.com/@aickin/whats-new-with-server-side-rendering-in-react-16-9b0d78585d67
ctx.res.write(header)
await pipe(stream, ctx.res, { end: false })
ctx.res.write(footer)
ctx.res.end()
})
// Pipes `from` stream to `to` stream.
// Returns a `Promise`.
function pipe(from, to, options)
{
return new Promise((resolve, reject) =>
{
from.pipe(to, options)
from.on('error', reject)
from.on('end', resolve)
})
}
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 set ctx.body
to the combined stream.
Ok, thanks
@PlasmaPower I've tried to play around with combined-stream but I'm struggling with it.
Following @catamphetamine's example, I can't get this to work:
const header = '<html><head></head><body>'
const footer = '</body></html>'
const combinedStream = CombinedStream.create()
combinedStream.write(header)
// https://medium.com/@aickin/whats-new-with-server-side-rendering-in-react-16-9b0d78585d67
const stream = renderToNodeStream()
combinedStream.append(stream)
combinedStream.pipe(ctx.body, { end : false }) // Triggers an error 'on' is not defined
combinedStream.write(footer)
I know I should let ctx.body
handle the stream, but I'm not sure how in that case.
ctx.body = combinedStream.pipe(..
?
@saxofficial Try multistream
import string_stream from 'string-to-stream'
import multi_stream from 'multistream'
ctx.status = 200
ctx.body = multi_stream
([
string_stream(before_content),
typeof content === 'string' ? string_stream(content) : content,
string_stream(after_content)
])
It works as part of react-isomorphic-render
.
@catamphetamine thanks, that works 👍
@catamphetamine let combinedStream = CombinedStream.create(); combinedStream.append(htmlTemplate[0]); combinedStream.append(stream); combinedStream.append(htmlTemplate[1]); ctx.body = combinedStream; it works~
don't use combinedStream.write directly. the API document said.
For anyone using node-fetch. This seems to work:
const response = await fetch(...)
ctx.body = response.body
You'll want to let Koa handle the stream:
ctx.body = ctx.req.pipe(request(`https://www.google.com/?q=${ctx.query.q}`));
ctx.req is a readable stream, so ctx.req.pipe(request(https://www.google.com/?q=${ctx.query.q}
)) will return the outgoing req--"request(https://www.google.com/?q=${ctx.query.q}
)".
Finally, koajs will pipe ctx.body to ctx.res, this will trigger error: OutgoingMessage should be write-only. Piping from it is disabled.
For anyone using node-fetch. This seems to work:
const response = await fetch(...) ctx.body = response.body
why native fetch not ok?
You'll want to let Koa handle the stream:
ctx.body = ctx.req.pipe(request(`https://www.google.com/?q=${ctx.query.q}`));
ctx.req is a readable stream, so ctx.req.pipe(request(
https://www.google.com/?q=${ctx.query.q}
)) will return the outgoing req--"request(https://www.google.com/?q=${ctx.query.q}
)".Finally, koajs will pipe ctx.body to ctx.res, this will trigger error: OutgoingMessage should be write-only. Piping from it is disabled.
ERR_STREAM_CANNOT_PIPE
koajs@2.13.1 nodejs@12.18.3
ctx.body = ctx.req.pipe(request({
headers, host: `${codeServerProxifier.host}`, path: url, method: ctx.method, // data: ctx.request.body,
agent: httpAgent, timeout: 6000,
}));
'request' package has deprecated. Can I know how to use 'axios' to stream response ctx.body?
I'm trying to pipe streams to my response but it seems didn't work
Simple test case:
An error occurred:
And
req.pipe(request(...)).pipe(res)
works in express.js, I'm wondering is there anything I do wrong?