14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LambdaからAppSyncをたたく

Posted at

ちょっとしたデモ用のシステムを作っていてLambdaからAppSyncを叩いてみたメモ。

AppSyncはCognitoのUserPoolで認証を設定している。
LambdaのハンドラではCognitoの認証処理を行い、認証トークンを利用してAppSyncにアクセスする。

Lambdaのハンドラーは次のような感じで実装する。

handler.ts
import { AuthenticationDetails, CognitoUser, CognitoUserPool } from 'amazon-cognito-identity-js';
import { Handler } from 'aws-lambda';

import gql from 'graphql-tag';
import AWSAppSyncClient from 'aws-appsync';
import {AUTH_TYPE} from 'aws-appsync/lib/link/auth-link';

// tslint:disable-next-line:no-var-requires
require('isomorphic-fetch');

export const handler: Handler = async (event, context, callback) => {
  const body = JSON.parse(event.body);

  // CognitoのUserPoolに登録したユーザのログイン情報
  const authenticationData = {
    Password: process.env.PASSWORD,
    Username: process.env.USERNAME,
  };
  const authenticationDetails = new AuthenticationDetails(authenticationData);

  const poolData = {
    ClientId: process.env.COGNITO_CLIENT_ID,
    UserPoolId: process.env.COGNITO_USER_POOL_ID,
  };
  const userPool = new CognitoUserPool(poolData);
  const userData = {
    Pool: userPool,
    Username: process.env.USERNAME,
  };
  const cognitoUser = new CognitoUser(userData);

  // AppSyncを叩くために認証トークンを取得する。
  // コールバック関数を渡すタイプの非同期処理になっているのでPromiseでくるんでAsync/Awaitで使いやすくする。
  const authenticateUser = async (): Promise<string> => {
    return new Promise((resolve, reject) => {
      cognitoUser.authenticateUser(authenticationDetails, {
        newPasswordRequired: (userAttributes, requiredAttributes) => {
          const err = new Error('newPasswordRequired');
          reject(err);
        },
        onFailure: (err) => {
          reject(err);
        },
        onSuccess: (result) => {
          const idToken = result.getIdToken().getJwtToken();
          resolve(idToken);
        },
      });
    });
  };
  const accessToken: string = await authenticateUser();

  // 以降は取得したトークンを使ってAppsyncにアクセスするところ。
  // AppSyncのSDKはPromiseに対応した実装になっているので使いやすい。
  const appsyncOpts = {
    auth: {
      jwtToken: accessToken,
      type: AUTH_TYPE.AMAZON_COGNITO_USER_POOLS,
    },
    disableOffline: true,
    region: process.env.APPSYNC_REGION,
    url: process.env.APPSYNC_ENDPOINT,
  };
  
  let response: {[key: string]: string|number};
  try {
    const appSyncClient = new AWSAppSyncClient(appsyncOpts); 

    // Mutationのリクエストを送信する
    const {data} = await this.client.mutate({
      mutation: gql(mutations.someMutation),
      variables: {input},
    });
    const mutatedObj = data.someMutation;

    response = {
      body: JSON.stringify({ result: 'SUCCESS', mutatedObj }),
      statusCode: 200,
    };

  } catch (error) {
    response = {
      body: JSON.stringify({ result: 'ERROR', name: error.name, message: error.message}),
      statusCode: 500,
    };
  }
  callback(null, response);
};

上記の例はMutationの例だけど、Queryの場合はappSyncClientがリクエストを送信する部分が次の様になるだけ。

const {data} = await appSyncClient.query({
  fetchPolicy: 'network-only',
  query: gql(queries.getObjectById),
  variables: {id},
});
const queriedObject = data.getObjectById;

参考

14
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?