Невозможно установить ctx.status и ctx.body Koajs при использовании запроса-обещания

В настоящее время я кодирую ручную настройку аутентификации приложения Shopify, аналогично тому, как они настраивают его в NodeJS и Express. Для приложения я использую NodeJS и фреймворк Koa. Я также использую @koa/router для маршрутизации и пытаюсь использовать запросы-обещания для создания внешнего HTTP. Запросы. Я не могу использовать промежуточное ПО Koa Authentication от Shopify, поскольку оно не работает с маршрутизаторами, и мне нужно, чтобы кодовая база поддерживала другие платформы электронной коммерции (BigCommerce, Magento и т. д.) в будущем.

Когда я получаю токен доступа или сообщение об ошибке, я не могу изменить ctx.status и ctx.body Koa в методах обещания .then() и .catch(). Как будто его просто игнорируют.

У меня есть следующие настройки для получения токена доступа:

const KoaRouter = require('@koa/router'),
const nonce = require('nonce')();
const querystring = require('querystring');
const crypto = require('crypto');
const dotenv = require('dotenv').config();
const request = require('request-promise');
const koaRequest = require('koa-http-request');

// Get Shopify information from the .env file
const apiKey = process.env.SHOPIFY_API_KEY;
const apiSecret = process.env.SHOPIFY_API_SECRET;
const scopes = process.env.SHOPIFY_SCOPE;

const router = new KoaRouter();

const getInstallURL = (shop) => {
  const state = nonce();
  const forwardingAddress = 'https://aecd64c2.ngrok.io'
  const redirectUri = forwardingAddress + '/shopify/auth/callback';
  return {
    "url": 'https://' + shop +
    '/admin/oauth/authorize?client_id=' + apiKey +
    '&scope=' + scopes +
    '&state=' + state +
    '&redirect_uri=' + redirectUri,
    "state": state
  };
}

const verifyHMAC = (query, hmac) => {
  const map = Object.assign({}, query);
  delete map['hmac'];
  const message = querystring.stringify(map);
  const providedHmac = Buffer.from(hmac, 'utf-8');
  const generatedHash = Buffer.from(
    crypto
      .createHmac('sha256', apiSecret)
      .update(message)
      .digest('hex'),
      'utf-8'
    );
  let hashEquals = false;
  // timingSafeEqual will prevent any timing attacks. Arguments must be buffers
  try {
    hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac)
  // timingSafeEqual will return an error if the input buffers are not the same length.
  } catch (e) {
    hashEquals = false;
  };

  return hashEquals;
};

const requestAccessToken = (shop, code) => {
  const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token';
  const accessTokenPayload = {
    client_id: apiKey,
    client_secret: apiSecret,
    code,
  };

  console.log('Requesting accessToken for ' + shop + "!");
  return request.post(accessTokenRequestUrl, { json: accessTokenPayload });
};

router.get('/shopify/auth', async (ctx, next) => {
  const shop = ctx.request.query.shop;
  console.log(shop);
  if (shop) {
    const ret = getInstallURL(shop);
    console.log(ret)
    ctx.cookies.set('state', ret['state']);
    ctx.redirect(ret['url']);
  } else {
    ctx.status=400;
    ctx.body='Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request';
  }
});

router.get('/shopify/auth/callback', async (ctx, next) => {
  const { shop, hmac, code, state } = ctx.request.query;
  const stateCookie = ctx.cookies.get('state');

  console.log(ctx.request.query);
  console.log(stateCookie);

  if (state !== stateCookie) {
    ctx.status = 403;
    ctx.body='Request origin cannot be verified';
  }

  if (shop && hmac && code) {
    if (!verifyHMAC(ctx.request.query, hmac)) {
      ctx.status = 400;
      ctx.body='HMAC validation failed';
    }

    console.log('Verified HMAC.  Now need to get access token');

    requestAccessToken(shop, code).then(
      (accessTokenResponse) => {
        const accessToken = accessTokenResponse.access_token;
        console.log('Access Token = ' + accessToken);

        ctx.status= 200;
        ctx.body= "Got an access token, let's do something with it";
      }
    ).catch(
      (error) => {
        console.log('An error has occurred!');
        console.log(error.statusCode);
        console.log(error.error.error_description);
        console.log(ctx.status);
        ctx.status = error.statusCode;
        ctx.body= error.error.error_description;
        console.log(ctx.status);
      }
    )

  } else {
    ctx.status = 400;
    ctx.body='Required parameters missing';
  }
});

module.exports = router;

Как я могу заставить переменную контекста Koa работать в Promise?


person Joseph Woolf    schedule 26.01.2020    source источник
comment
ctx не определено   -  person Ahmet Zeybek    schedule 26.01.2020
comment
Я добавил полный пример кода для аутентификации приложения Shopify в магазине Shopify.   -  person Joseph Woolf    schedule 26.01.2020
comment
Не могли бы вы получить токен доступа от shopify?   -  person Ahmet Zeybek    schedule 26.01.2020
comment
Я могу получить токен доступа. Однако Koa возвращает ошибку 404. Это говорит мне о том, что по какой-то причине изменения ctx игнорируются в методе обещания .then().   -  person Joseph Woolf    schedule 26.01.2020
comment
Я отправил ответ, проверьте его, пожалуйста. Если не работает, я могу помочь вам с VS LiveShare или TeamViewer.   -  person Ahmet Zeybek    schedule 26.01.2020


Ответы (1)


Можете ли вы отредактировать свою функцию requestAccessToken, как показано ниже. Вы не можете использовать метод .then(), если функция не определена как асинхронная.

const requestAccessToken = async (shop, code) => {
  const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token';
  const accessTokenPayload = {
    client_id: apiKey,
    client_secret: apiSecret,
    code,
  };

  console.log('Requesting accessToken for ' + shop + "!");
  return await request.post(accessTokenRequestUrl, { json: accessTokenPayload });
};
person Ahmet Zeybek    schedule 26.01.2020
comment
Заставить функцию работать асинхронно. Однако ожидание возвращенного обещания не сработало. Помещение await в строку requestAccessToken(shop, code).then(...) сработало и позволило мне изменить ctx. - person Joseph Woolf; 26.01.2020
comment
Да, мне не нужно было писать, потому что я думал, что вы могли бы догадаться - person Ahmet Zeybek; 26.01.2020