I've set up a custom server.js, and also create an api as /pages/api/mock.ts.
The problem is, when I tried to fetch('api/mock'), I always got response with content OK instead of a JSON. But if I start Next app without custom server, api routes works as expected.
I cannot find examples for using API route with a custom server. Here's my configuration:
In server.js
const Koa = require('koa');
const Router = require('koa-router');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const port = process.env.PORT || 3000;
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.use(router.routes());
/* some routes except `/api/` */
router.get('*', async (ctx, next) => {
await handle(ctx.req, ctx.res);
});
server.listen(port, err => {
if (err) {
throw err;
}
console.log(`> WEB Ready on http://localhost:${port}`);
});
});
/pages/api/mock.ts
export default (_: NextApiRequest, res: NextApiResponse) => {
// this will be triggered but it send 'OK' back instead of a JSON string
console.log('hit');
const mock = JSON.stringify({data: 'foo' });
res.setHeader('Content-Type', 'application/json; charset=UTF-8');
res.statusCode = 200;
res.end(mock);
};
Please clone this repo: https://github.com/jesseminn/next-bug-demo
I also was having same situation previously, i was having wrong directory name for the apis, it should be api.
Now your case, shouldn't it be pages???
I also was having same situation previously, i was having wrong directory name for the apis, it should be api.
Now your case, shouldn't it be pages???
Sorry I've corrected the typo. I did put it in pages/api/, and the controller is triggered but did not send back the JSON.
how do you run your app?? I hope you do build the next and then do the custom server run?
how do you run your app?? I hope you do build the next and then do the custom server run?
I starts the server with nodemon in dev & with node in production mode, both way have the same issue.
I just tested it and it works fine. Could you provide minimal reproduction where an error occurs?
maybe you have conflicting routes, e.g. with a dynamic first part /:somethingDynamic/ which gets called when you'd expect /api/ to be called. try handling the /api/ route first or disambiguate:
router.get('/api/:params?', async (ctx, next) => {
await handle(ctx.req, ctx.res);
});
server.use(router.routes());
I think the main issue here would be that req.url might be wrong because of the framework you're using, we've seen this happen before with express apps 馃
maybe you have conflicting routes, e.g. with a dynamic first part
/:somethingDynamic/which gets called when you'd expect/api/to be called. try handling the/api/route first or disambiguate:router.get('/api/:params?', async (ctx, next) => { await handle(ctx.req, ctx.res); }); server.use(router.routes());
Hi, thanks for reply. I've tried adding the route but didn't fix the problem.
I've added a small example to reproduce the issue, please check https://github.com/jesseminn/next-bug-demo
Thanks!
i haven't used koa before, so i can't tell if there's a problem with it. the code looks reasonable to me, though. when i exchange koa for express in your repo, it works.
Found the solution. I think it's because Koa has built-in response handling, and setting ctx.respond = false can bypass it. Check the official documentation about ctx.respond
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.use(router.routes());
/* some routes except `/api/` */
router.get('*', async (ctx, next) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
});
server.listen(port, err => {
if (err) {
throw err;
}
console.log(`> WEB Ready on http://localhost:${port}`);
});
});
Most helpful comment
Found the solution. I think it's because Koa has built-in response handling, and setting
ctx.respond = falsecan bypass it. Check the official documentation aboutctx.respond