The Koa example uses ctx.respond, but the Koa documentation says: "Note that using this is not supported by Koa. This may break intended functionality of Koa middleware and Koa itself. Using this property is considered a hack and is only a convenience to those wishing to use traditional fn(req, res) functions and middleware within Koa."
Can this be avoided and if yes, could the example be updated?
Until someone comes up with a better solution I'm currently running with a hacky little workaround I threw together. Here's a (slightly modified) excerpt from my routing code:
export const myRoute = ({ next }) =>
handle(({ req, res, params }) => next.render(req, res, '/my-route', params));
export const catchAll = ({ handler }) =>
handle(({ req, res }) => handler(req, res));
function handle(middleware) {
return async ctx => {
ctx.body = await new Promise(resolve => {
const _end = ctx.res.end;
// Hijack stream to set ctx.body
const pipe = stream => {
ctx.res.end = _end;
stream.unpipe(ctx.res);
resolve(stream);
};
ctx.res.once('pipe', pipe);
// Monkey patch res.end to set ctx.body
ctx.res.end = body => {
ctx.res.end = _end;
ctx.res.removeListener('pipe', pipe);
resolve(body);
};
middleware(ctx);
});
};
}
For now it's actually working really well, but I feel like it could break at any point with any update.
I'd love it if there was a supported way of achieving this.
Thanks for sharing @dizlexik, works perfectly 馃憣
+1 for a proper solution to this... although I can't really see a non-hacky solution as long as next.js handles request/response itself.
Bummer that this was closed. I sure would love to see proper Koa support via a more configurable side-effect-free rendering pipeline. Running my hack in production right now doesn't feel great but I'm forced to do it if I want to use Koa :/
maybe we can contact someone from the @koajs team to take a look?
I think the real solution to this would be to opt-out of next.js's request handling 鈥斅爐hat there would be an API to extract a response body (and perhaps headers?), so it could be used in various server configurations.
So you'd have the entire next.js rendering pipeline but it simply wouldn't send the response.
@dizlexik Does your above code snippet work for you with server side redirects? It seems to work nicely when rendering pages however if I do a server side redirect (eg from inside getInitialProps, eg https://github.com/zeit/next.js/wiki/Redirecting-in-%60getInitialProps%60) the response never seems to terminate & client never receives a response
Just got around to testing this out and the server-side redirect worked fine for me. I'm not sure why it's hanging for you, sorry :/
Hey @stevegeek, I was testing without res.finished = true and it was working perfectly in development mode. But I did go back and try with it included and got the hanging you were talking about.
However, I just got back around to this and tested in production mode and started getting errors about headers already being sent. Monkey patching wasn't an option for writeHead so I created a new redirect method and added it after the ctx.res.end monkey patching code in my hack above:
// Create res.redirect method
ctx.res.redirect = (url, status, message) => {
if (status) ctx.status = status;
ctx.redirect(url);
if (message) ctx.body = message;
};
And I'm now calling that from within getInitialProps, e.g. res.redirect('/page', 302)
Btw the redirect code follows the Koa documentation: http://koajs.com/#response-redirect-url-alt-
@dizlexik Thanks for the update. I really wish it was possible to opt out of the response handling in next then the work arounds would not be necessary
This thread has been automatically locked because it has not had recent activity. Please open a new issue for related bugs and link to relevant comments in this thread.
Most helpful comment
Bummer that this was closed. I sure would love to see proper Koa support via a more configurable side-effect-free rendering pipeline. Running my hack in production right now doesn't feel great but I'm forced to do it if I want to use Koa :/