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にクローズされました