Could not post to Koa Route, always returning 404

Highlighted
New Member
1 0 0

Hello everyone,

I need help understanding how koa-router works within a shopify app. I have setup a post route for saving API credentials for integration with our third-party service, but it always returns 404 not found.

 

Here is my server.js code

require('isomorphic-fetch');
const dotenv = require('dotenv');
const Koa = require('koa');
const next = require('next');
const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth');
const { verifyRequest } = require('@shopify/koa-shopify-auth');
const session = require('koa-session');
const Router = require('koa-router');
const koaBody = require('koa-body');
const Boom = require('boom');
dotenv.config();
const port = parseInt(process.env.PORT, 10) || 8080;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

const credentialService = require('./classes/services/credentialService');
const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env;


app.prepare().then(() => {
  const server = new Koa();
  const router = new Router();
  server.use(session({ secure: true, sameSite: 'none' }, server));
  server.keys = [SHOPIFY_API_SECRET_KEY];

  server.use(
    createShopifyAuth({
      apiKey: SHOPIFY_API_KEY,
      secret: SHOPIFY_API_SECRET_KEY,
      scopes: ['read_orders'],
      afterAuth(ctx) {
        const { shop, accessToken } = ctx.session;
        console.log({ shop });
        ctx.cookies.set('shopOrigin', shop, {
          httpOnly: false,
          secure: true,
          sameSite: 'none'
        });
        ctx.redirect('/');
      },
    }),
  )
  .use(verifyRequest())
  .use(async (ctx) => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
    return;
  })
  .use(router.allowedMethods({
    throw: true,
    notImplemented: () => new Boom.notImplemented(),
    methodNotAllowed: () => new Boom.methodNotAllowed()
  }))
  .use(router.routes());

  router.post('/settings', koaBody(), async (ctx, next) => {
    try {
      const { appId, publicKey, secret, daysPolicy, sandbox } = ctx.request.body;
      const saveSettings = await credentialService.saveCredential(ctx.cookies.get('shopOrigin'), appId, publicKey, secret, daysPolicy, sandbox);
      console.log({ saveSettings });
      ctx.res.statusCode = 201;
      ctx.body = JSON.stringify(ctx.request.body);
    }
    catch (e) {
      console.log(e);
      ctx.res.statusCode = 500;
    }
  })

  server.listen(port, () => {
    console.log(`> Ready on http://localhost:${port}`);
  });
});

 

Badly stuck on this step as I am used to using Express.js and not Koa-router. Would appreciate any help that anyone can provide.

0 Likes
Highlighted
New Member
4 0 0

I'm stuck on this part also, have you tried using the verify request function from shopify koa as middleware? 

0 Likes
Highlighted
Shopify Partner
66 5 25

Koa routing is done by precedence.

Right now, you are mounting your NextJS routes before your custom POST route. And Next does catchall routing internally.

 

  server.use(
    createShopifyAuth({
      apiKey: SHOPIFY_API_KEY,
      secret: SHOPIFY_API_SECRET_KEY,
      scopes: ['read_orders'],
      afterAuth(ctx) {
        const { shop, accessToken } = ctx.session;
        console.log({ shop });
        ctx.cookies.set('shopOrigin', shop, {
          httpOnly: false,
          secure: true,
          sameSite: 'none'
        });
        ctx.redirect('/');
      },
    }),
  )

  server.use(verifyRequest())

  router.post('/settings', koaBody(), async (ctx, next) => {
    try {
      const { appId, publicKey, secret, daysPolicy, sandbox } = ctx.request.body;
      const saveSettings = await credentialService.saveCredential(ctx.cookies.get('shopOrigin'), appId, publicKey, secret, daysPolicy, sandbox);
      console.log({ saveSettings });
      ctx.res.statusCode = 201;
      ctx.body = JSON.stringify(ctx.request.body);
    }
    catch (e) {
      console.log(e);
      ctx.res.statusCode = 500;
    }
  })

  server.use(async (ctx) => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
    return;
  })
  server.use(router.allowedMethods({
    throw: true,
    notImplemented: () => new Boom.notImplemented(),
    methodNotAllowed: () => new Boom.methodNotAllowed()
  }))
  server.use(router.routes());

 

0 Likes