入門 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'Pinned Articles
About
ウェブ界隈でエンジニアとして労働活動に励んでいる @gomi_ningen 個人のブログです
Tags
LLM
promptfoo
GenAI
JavaScript
PowerShell
kibana
fluentd
elasticsearch
nginx
村川梨衣
五十嵐裕美
イベント
logrotate
IoT
Java
Scala
iputils
C言語
ICMP
WUG
mastodon
Swift
AWS
Clock
Windows
アーキテクチャ
PoEAA
iOS
DeviceFarm
プログラミング言語
OS
Lambda
StepFunctions
Serverless
terraform
ポエム
RHEL
ネットワーク
GraphQL
CloudWatch
Linux
Coreutils
telnet
network
nc
LinuxKernel
fpinscala
ELB
IAM
AppSync