Name:
interface
Value:
Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Page updated Mar 20, 2024

Maintenance ModeYou are viewing Amplify Gen 1 documentation. Amplify Gen 1 has entered maintenance mode and will reach end of life on May 1, 2027. New project should use Amplify Gen 2. For existing Gen 1 projects, a migration guide and tooling are available to help you upgrade. Switch to the latest Gen 2 docs →

Lambda 関数から GraphQL API を呼び出す

Node.js アプリまたは Lambda 関数から AppSync GraphQL API を呼び出すことができます。基本的な Todo アプリを例として考えます:

type Todo @model @auth(rules: [{ allow: public }]) {
name: String
description: String
}

この API には QueryMutationSubscription の操作が利用可能です。Node.js を使用して Lambda 関数からクエリミューテーションの両方を実行する方法を見てみましょう。

Lambda 関数テンプレートの利用 (IAM 認可)

まず、amplify add function で Lambda 関数を作成し、AppSync - GraphQL API request (with IAM) を選択して開始します。CLI がプロジェクト内の他のリソースへのアクセスを許可するよう促した場合は、GraphQL API へのアクセスを許可してください。または、ゼロから作成することもできます。

amplify add function
? Select which capability you want to add: Lambda function (serverless function)
? Provide an AWS Lambda function name: myfunction
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: AppSync - GraphQL API request (with IAM)
Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration
- Environment variables configuration
- Secret values configuration
? Do you want to configure advanced settings? Yes
? Do you want to access other resources in this project from your Lambda function? Yes
? Select the categories you want this function to have access to. api
? Select the operations you want to permit on <YOUR_API_NAME> Query, Mutation, Subscription
You can access the following resource attributes as environment variables from your Lambda function
API_<YOUR_API_NAME>_GRAPHQLAPIENDPOINTOUTPUT
API_<YOUR_API_NAME>_GRAPHQLAPIIDOUTPUT
API_<YOUR_API_NAME>_GRAPHQLAPIKEYOUTPUT
ENV
REGION

この関数は IAM 認可を使用する GraphQL API が存在する場合にのみ追加できます。

ゼロから作成

amplify add function
? Select which capability you want to add: Lambda function (serverless function)
? Provide an AWS Lambda function name: myfunction
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Hello World
Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration
- Environment variables configuration
- Secret values configuration
? Do you want to configure advanced settings? Yes
? Do you want to access other resources in this project from your Lambda function? Yes
? Select the categories you want this function to have access to. api
? Select the operations you want to permit on <YOUR_API_NAME> Query, Mutation, Subscription
You can access the following resource attributes as environment variables from your Lambda function
API_<YOUR_API_NAME>_GRAPHQLAPIENDPOINTOUTPUT
API_<YOUR_API_NAME>_GRAPHQLAPIIDOUTPUT
API_<YOUR_API_NAME>_GRAPHQLAPIKEYOUTPUT
ENV
REGION

このページの例では、node-fetch を使用して GraphQL API への HTTP リクエストを作成します。Node.js v18 ランタイムが Lambda 用にリリースされると、この依存関係は ネイティブ fetch に置き換えることができます。開始するには、node-fetch モジュールを依存関係として追加します:

CommonJS:

CommonJS を使用して記述された関数の場合、node-fetch のバージョン 2 をインストールする必要があります

{
"name": "myfunction",
"version": "2.0.0",
"description": "Lambda function generated by Amplify",
"main": "index.js",
"license": "Apache-2.0",
+ "dependencies": {
+ "node-fetch": "2"
+ },
"devDependencies": {
"@types/aws-lambda": "^8.10.92"
}
}

ESM:

{
"name": "myfunction",
+ "type": "module",
"version": "2.0.0",
"description": "Lambda function generated by Amplify",
"main": "index.js",
"license": "Apache-2.0",
+ "dependencies": {
+ "node-fetch": "^3.2.3"
+ },
"devDependencies": {
"@types/aws-lambda": "^8.10.92"
}
}

クエリ

API キーを使用してリクエストを認証すると、GraphQL API をクエリして、すべての Todo のリストを取得できます。リスト クエリにページネーションを行うには、listTodos クエリに limitnextToken を渡す必要があります。詳細は GraphQL ページネーション を参照してください。

import { default as fetch, Request } from 'node-fetch';
const GRAPHQL_ENDPOINT = process.env.API_<YOUR_API_NAME>_GRAPHQLAPIENDPOINTOUTPUT;
const GRAPHQL_API_KEY = process.env.API_<YOUR_API_NAME>_GRAPHQLAPIKEYOUTPUT;
const query = /* GraphQL */ `
query LIST_TODOS {
listTodos {
items {
id
name
description
}
}
}
`;
/**
* @type {import('@types/aws-lambda').APIGatewayProxyHandler}
*/
export const handler = async (event) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
/** @type {import('node-fetch').RequestInit} */
const options = {
method: 'POST',
headers: {
'x-api-key': GRAPHQL_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({ query })
};
const request = new Request(GRAPHQL_ENDPOINT, options);
let statusCode = 200;
let body;
let response;
try {
response = await fetch(request);
body = await response.json();
if (body.errors) statusCode = 400;
} catch (error) {
statusCode = 400;
body = {
errors: [
{
status: response.status,
message: error.message,
stack: error.stack
}
]
};
}
return {
statusCode,
body: JSON.stringify(body)
};
};

ミューテーション

この例では、変数を引数として渡して Todo レコードを作成する方法を示すミューテーションを作成します。

import { default as fetch, Request } from 'node-fetch';
const GRAPHQL_ENDPOINT = process.env.API_<YOUR_API_NAME>_GRAPHQLAPIENDPOINTOUTPUT;
const GRAPHQL_API_KEY = process.env.API_<YOUR_API_NAME>_GRAPHQLAPIKEYOUTPUT;
const query = /* GraphQL */ `
mutation CREATE_TODO($input: CreateTodoInput!) {
createTodo(input: $input) {
id
name
createdAt
}
}
`;
/**
* @type {import('@types/aws-lambda').APIGatewayProxyHandler}
*/
export const handler = async (event) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
const variables = {
input: {
name: 'Hello, Todo!'
}
};
/** @type {import('node-fetch').RequestInit} */
const options = {
method: 'POST',
headers: {
'x-api-key': GRAPHQL_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({ query, variables })
};
const request = new Request(GRAPHQL_ENDPOINT, options);
let statusCode = 200;
let body;
let response;
try {
response = await fetch(request);
body = await response.json();
if (body.errors) statusCode = 400;
} catch (error) {
statusCode = 400;
body = {
errors: [
{
status: response.status,
message: error.message,
stack: error.stack
}
]
};
}
return {
statusCode,
body: JSON.stringify(body)
};
};

IAM 認可

iam 認可を使用する別のスキーマ例を見てみましょう。

type Todo @model @auth(rules: [{ allow: private, provider: iam }]) {
name: String
description: String
}

CLI は Lambda 実行 IAM ロールを自動的に構成して GraphQL API を呼び出します。Lambda 関数を記述する前に、適切な AWS SDK v3 依存関係をインストールする必要があります:

{
"name": "myfunction",
+ "type": "module",
"version": "2.0.0",
"description": "Lambda function generated by Amplify",
"main": "index.js",
"license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-js": "^2.0.1",
+ "@aws-sdk/credential-provider-node": "^3.76.0",
+ "@aws-sdk/protocol-http": "^3.58.0",
+ "@aws-sdk/signature-v4": "^3.58.0",
+ "node-fetch": "^3.2.3"
+ },
"devDependencies": {
"@types/aws-lambda": "^8.10.92"
}
}

その後、以下の例は IAM 認可を使用して GraphQL API を呼び出すリクエストに署名します。

import crypto from '@aws-crypto/sha256-js';
import { defaultProvider } from '@aws-sdk/credential-provider-node';
import { SignatureV4 } from '@aws-sdk/signature-v4';
import { HttpRequest } from '@aws-sdk/protocol-http';
import { default as fetch, Request } from 'node-fetch';
const { Sha256 } = crypto;
const GRAPHQL_ENDPOINT = process.env.API_<YOUR_API_NAME>_GRAPHQLAPIENDPOINTOUTPUT;
const AWS_REGION = process.env.AWS_REGION || 'us-east-1';
const query = /* GraphQL */ `
query LIST_TODOS {
listTodos {
items {
id
name
description
}
}
}
`;
/**
* @type {import('@types/aws-lambda').APIGatewayProxyHandler}
*/
export const handler = async (event) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
const endpoint = new URL(GRAPHQL_ENDPOINT);
const signer = new SignatureV4({
credentials: defaultProvider(),
region: AWS_REGION,
service: 'appsync',
sha256: Sha256
});
const requestToBeSigned = new HttpRequest({
method: 'POST',
headers: {
'Content-Type': 'application/json',
host: endpoint.host
},
hostname: endpoint.host,
body: JSON.stringify({ query }),
path: endpoint.pathname
});
const signed = await signer.sign(requestToBeSigned);
const request = new Request(GRAPHQL_ENDPOINT, signed);
let statusCode = 200;
let body;
let response;
try {
response = await fetch(request);
body = await response.json();
if (body.errors) statusCode = 400;
} catch (error) {
statusCode = 500;
body = {
errors: [
{
message: error.message
}
]
};
}
return {
statusCode,
body: JSON.stringify(body)
};
};

CommonJS

CommonJS で関数を記述する場合、node-fetch のバージョン 2 をインストールする必要があります:

{
"name": "myfunction",
"version": "2.0.0",
"description": "Lambda function generated by Amplify",
"main": "index.js",
"license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-js": "^2.0.1",
+ "@aws-sdk/credential-provider-node": "^3.76.0",
+ "@aws-sdk/protocol-http": "^3.58.0",
+ "@aws-sdk/signature-v4": "^3.58.0",
+ "node-fetch": "2"
+ },
"devDependencies": {
"@types/aws-lambda": "^8.10.92"
}
}

上記の例と同様に、ハンドラーを記述できます。ここでの違いは import ... from ではなく require() を使用することです。

const { Sha256 } = require('@aws-crypto/sha256-js');
const { defaultProvider } = require('@aws-sdk/credential-provider-node');
const { SignatureV4 } = require('@aws-sdk/signature-v4');
const { HttpRequest } = require('@aws-sdk/protocol-http');
const { default: fetch, Request } = require('node-fetch');
const GRAPHQL_ENDPOINT =
process.env.API_ < YOUR_API_NAME > _GRAPHQLAPIENDPOINTOUTPUT;
const AWS_REGION = process.env.AWS_REGION || 'us-east-1';
const query = /* GraphQL */ `
query LIST_TODOS {
listTodos {
items {
id
name
description
}
}
}
`;
/**
* @type {import('@types/aws-lambda').APIGatewayProxyHandler}
*/
exports.handler = async (event) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
const endpoint = new URL(GRAPHQL_ENDPOINT);
const signer = new SignatureV4({
credentials: defaultProvider(),
region: AWS_REGION,
service: 'appsync',
sha256: Sha256
});
const requestToBeSigned = new HttpRequest({
method: 'POST',
headers: {
'Content-Type': 'application/json',
host: endpoint.host
},
hostname: endpoint.host,
body: JSON.stringify({ query }),
path: endpoint.pathname
});
const signed = await signer.sign(requestToBeSigned);
const request = new Request(GRAPHQL_ENDPOINT, signed);
let statusCode = 200;
let body;
let response;
try {
response = await fetch(request);
body = await response.json();
if (body.errors) statusCode = 400;
} catch (error) {
statusCode = 500;
body = {
errors: [
{
message: error.message
}
]
};
}
return {
statusCode,
body: JSON.stringify(body)
};
};