@gomi_ningen's Website

AppSync ことはじめ

入門 1: AppSync で Hello, World!

まず AppSync で "Hello, World!" という文字列を返す単純な GraphQL API を作成し、サービスの利用法をみていきます

スキーマの作成

まずは GraphQL SDL(Schema Definition Language) を用いて GraphQL API のインターフェースを定義していきます。次のような単純な User データを返却する user クエリを定義します。

schema { query: Query } type Query { user(id: ID!): User } type User { id: ID! name: String! }

データソース/リゾルバの作成

ことはじめとして、決まった値を返すようなリゾルバを定義します。

{ "id": 1, "name": "hoge" }

データソースは None タイプを選択したものを指定し、レスポンスマッピングテンプレートにて前述の定数値を返すように設定します。

クエリの実行

次のようなクエリを実行します。定数値を返すレスポンスマッピングテンプレートを設定しているので id を変えても常に同じ値が帰ります。name のみにすると、戻り値に id は含まれなくなります。

query { user(id: 1) { id name } }

SAM テンプレート

CloudFormation テンプレートで以上のリソースを表現しておくとわかりやすいかもしれません。次のようになります。

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > Hello AppSync Resources: GraphQLApi: Type: AWS::AppSync::GraphQLApi Properties: Name: GraphQLHello AuthenticationType: API_KEY GraphQLSchema: Type: AWS::AppSync::GraphQLSchema Properties: ApiId: !GetAtt GraphQLApi.ApiId DefinitionS3Location: schema.graphql GraphQLNoneDataSource: Type: AWS::AppSync::DataSource Properties: Name: GraphQLNoneDataSource ApiId: !GetAtt GraphQLApi.ApiId Type: NONE GraphQLResolver: Type: AWS::AppSync::Resolver Properties: ApiId: !GetAtt GraphQLApi.ApiId TypeName: Query FieldName: user DataSourceName: !GetAtt GraphQLNoneDataSource.Name RequestMappingTemplate: '{"version": "2017-02-28", "payload": {}}' ResponseMappingTemplate: '{"id":1, "name":"hoge"}' GraphQLAPIKey: Type: AWS::AppSync::ApiKey Properties: ApiId: !GetAtt GraphQLApi.ApiId

入門 2: 値を Lambda データソースから返却する

定数値をレスポンスマッピングテンプレートから返却するのではなく、Lambda 関数から返してみます。

データソースの作成

以下のような単純な Lambda 関数を作成し、これをデータソースとして指定します。

import json def lambda_handler(event, context): print(json.dumps(event, ensure_ascii=False)) return { 'id': event['id'], 'name': 'hogefuga' }

リゾルバの作成

リゾルバのマッピングテンプレートを以下のように設定すると背後にある Lambda 関数をデータソースとして呼び出せます

# request { "version" : "2017-02-28", "operation": "Invoke", "payload": $util.toJson($context.args) } # response $util.toJson($context.result)

クエリの実行

以下のようなクエリを実行すると無事 Lambda から返却された id に対応するレスポンスが得られます(name は固定値ですが...)。

query { user(id: 123) { id name } }

あわせて Lambda 関数の CloudWatch Logs をみると以下のようなイベントが渡っていることがわかります

{ 'id': '123' }

SAM テンプレート

Lambda 関数が絡んできたので SAM が生きます。テンプレートは以下のようなもの。AppSync から Lambda を実行する際の実行ロールがやや冗長なので、スマートにかけるようになると便利そうですね。

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > Hello AppSync Resources: GraphQLApi: Type: AWS::AppSync::GraphQLApi Properties: Name: GraphQLHello AuthenticationType: API_KEY GraphQLSchema: Type: AWS::AppSync::GraphQLSchema Properties: ApiId: !GetAtt GraphQLApi.ApiId DefinitionS3Location: schema.graphql GraphQLDataSourceLambdaFunction: Type: AWS::Serverless::Function Properties: CodeUri: get_user/ Handler: app.lambda_handler Runtime: python3.8 AppSyncLambdaInvokeRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: appsync.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: AllowInvokeLambda PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: lambda:invokeFunction Resource: !GetAtt GraphQLDataSourceLambdaFunction.Arn GraphQLLambdaDataSource: Type: AWS::AppSync::DataSource Properties: Name: GraphQLLambdaDataSource ApiId: !GetAtt GraphQLApi.ApiId Type: AWS_LAMBDA LambdaConfig: LambdaFunctionArn: !GetAtt GraphQLDataSourceLambdaFunction.Arn ServiceRoleArn: !GetAtt AppSyncLambdaInvokeRole.Arn GraphQLResolver: Type: AWS::AppSync::Resolver Properties: ApiId: !GetAtt GraphQLApi.ApiId TypeName: Query FieldName: user DataSourceName: !GetAtt GraphQLLambdaDataSource.Name RequestMappingTemplate: '{ "version" : "2017-02-28", "operation": "Invoke", "payload": $util.toJson($context.args) }' ResponseMappingTemplate: '$util.toJson($context.result)' GraphQLAPIKey: Type: AWS::AppSync::ApiKey Properties: ApiId: !GetAtt GraphQLApi.ApiId

入門 3: HTTP データソースの利用

  • スキーマは以前と同様にデータソースを HTTP データソースに変更してみる
  • 簡単のため JSONPlaceholder の Users API を叩く

データソースの作成

JSONPlaceholder のエンドポイント: https://jsonplaceholder.typicode.com を指定し、データソースを作成する

リゾルバの作成

リゾルバのマッピングテンプレートを以下のように設定すると背後にある HTTP エンドポイントをデータソースとして呼び出せる

# request {"version":"2018-05-29","method":"GET","resourcePath":"/users/$ctx.args.id"} # response $context.result.body

クエリの実行

以下のようなクエリを実行する

query { get(id: "3") { id name } }

すると以下のような結果が得られる

{ "data": { "get": { "id": "3", "name": "Clementine Bauch" } } }

SAM テンプレート

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > Hello AppSync Resources: GraphQLApi: Type: AWS::AppSync::GraphQLApi Properties: Name: GraphQLHello AuthenticationType: API_KEY GraphQLSchema: Type: AWS::AppSync::GraphQLSchema Properties: ApiId: !GetAtt GraphQLApi.ApiId DefinitionS3Location: schema.graphql GraphQLAPIKey: Type: AWS::AppSync::ApiKey Properties: ApiId: !GetAtt GraphQLApi.ApiId GraphQLHTTPDataSource: Type: AWS::AppSync::DataSource Properties: Name: GraphQLHTTPDataSource ApiId: !GetAtt GraphQLApi.ApiId Type: HTTP HttpConfig: Endpoint: https://jsonplaceholder.typicode.com GraphQLResolver: Type: AWS::AppSync::Resolver Properties: ApiId: !GetAtt GraphQLApi.ApiId TypeName: Query FieldName: user DataSourceName: !GetAtt GraphQLHTTPDataSource.Name RequestMappingTemplate: '{"version":"2018-05-29","method":"GET","resourcePath":"/users/$ctx.args.id"}' ResponseMappingTemplate: '$context.result.body'

Copyright © 53ningen.com