Closed11
AWS AppSync JavaScript ResolverでHTTPデータソース(REST API)からデータを収集する
最近(2022/10)AppSyncのリゾルバがJavaScriptに対応したそうなのでこれを使ってREST APIを叩くリゾルバを書いてみたい
参考資料
- https://aws.amazon.com/jp/blogs/news/aws-appsync-graphql-apis-supports-javascript-resolvers/
- https://aws.amazon.com/jp/blogs/news/getting-started-with-javascript-resolvers-in-aws-appsync-graphql-apis/
- https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html
- https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-http-js.html
ハマったポイントとか
- HTTPデータソースから取得した結果は
ctx.result.bodyから取り出す(レスポンスボディだからそれはそう) -
ctx.result.bodyは文字列なのでJSON.parse()する必要がある - HTTPデータソースにAPI Gatewayで作成したAPIを使う場合、エンドポイントのURLはステージ名(
/devとか)を含まないものにする必要がある- トラブルシュート時にREST APIへの疎通を確認したくてAPI Gatewayでモックを作って叩こうとしたが、エンドポイントに
https://xxx.amazonaws.com/devまでのURLを指定したらtemplate transformation yelded an empty responseというエラーになった
- トラブルシュート時にREST APIへの疎通を確認したくてAPI Gatewayでモックを作って叩こうとしたが、エンドポイントに
- 親リゾルバの結果は
ctx.sourceに格納されている
エンドポイントのURLにステージ名を入れるなというのは公式のチュートリアルに書いてあった

Pipeline Resolver
- Pipeline Resolverは以下の順で処理を実行して最終的な結果をリゾルバの戻り値として使う
- 前処理
- 最大10件のFunction
- 後処理
- AppSyncのコンソールでスキーマのフィールドにリゾルバをアタッチすると、Pipeline Resolverになる
- 任意のデータソースに対する処理を関数(Function)として定義しておいて、Pipeline Resolverから参照する
題材
- Apollo Odysseyのアプリ(Catstronauts)のバックエンドの一部をAppSyncで再現する

type Query {
tracksForHome: [Track!]!
}
type Track {
id: ID!
title: String!
author: Author!
thumbnail: String
length: Int
modulesCount: Int
}
type Author {
id: ID!
name: String!
photo: String
}
APIの作成
-
AppSyncのコンソールから
APIを作成 -
一から構築を選択して開始- とりあえず動くAPIを作りたい場合は
サンプルプロジェクトから開始するからイベントアプリなどを選択して作成するとDynamoDBをリソースとして直接読み書きするAPIが作れる
- とりあえず動くAPIを作りたい場合は

データソースの定義
- コンソールの左側から
データソース>データソースを作成 - 任意のデータソース名を入力
-
catstronauts_rest_apiとした
-
- データソースタイプは
HTTPエンドポイント - HTTPエンドポイントはAPIのベースURL
- 叩きたいAPIが
https://example.com/fooならhttps://example.comを指定する - Apollo Odysseyで叩いていたエンドポイントは https://odyssey-lift-off-rest-api.herokuapp.com
- 叩きたいAPIが

関数の定義
REST APIを叩いて結果を戻す関数を作成する
- コンソールの左側から
関数>関数を作成 - 作成したデータソースを選択
- 関数名を入力
- Apollo Odysseyに倣って
getTracksForHomeとした
- Apollo Odysseyに倣って

関数コード
import { util } from '@aws-appsync/utils';
export function request(ctx) {
return {
method: 'GET',
params: {
headers: { 'Content-Type': 'application/json' },
},
resourcePath: '/tracks',
};
}
export function response(ctx) {
const { error, result } = ctx;
if (error) {
ctx.stash.errors = ctx.stash.errors ?? [];
ctx.stash.errors.push(ctx.error);
return util.appendError(error.message, error.type, result);
}
if (result.statusCode === 200) {
return JSON.parse(result.body);
} else {
return util.appendError(result.body, result.statusCode);
}
}
スキーマにリゾルバをアタッチ
スキーマタブで画面右側、リゾルバーペインからtracksForHome: [Track!]!クエリのアタッチを押す

右下の方にある関数を追加 > getTracksForHomeを選択

関数が追加される

画面右上の作成を押して保存するとPipelineリゾルバがクエリにアタッチされた状態になる

クエリを実行してみる
Authorのリゾルバは未作成なので外してクエリを投げると結果が戻ってくる

ネストされたフィールドのリゾルバを書く
関数getAuthorを追加する
import { util } from '@aws-appsync/utils';
export function request(ctx) {
return {
method: 'GET',
params: {
headers: { 'Content-Type': 'application/json' },
},
resourcePath: `/author/${ctx.source.authorId}`,
};
}
export function response(ctx) {
const { error, result } = ctx;
if (error) {
ctx.stash.errors = ctx.stash.errors ?? [];
ctx.stash.errors.push(ctx.error);
return util.appendError(error.message, error.type, result);
}
if (result.statusCode === 200) {
return JSON.parse(result.body);
} else {
return util.appendError(result.body, result.statusCode);
}
}
動いた

このスクラップは2023/01/06にクローズされました
