LoginSignup
16
10

More than 5 years have passed since last update.

AppSync上のGraphQL APIをapollo-linkで呼ぶ(Lambdaからも)

Last updated at Posted at 2018-12-29

なぜこれを書くのか

image.png

GraphQLといえば、手軽さでいうとこのマネージドサービス、AWS AppSyncが出てきます。
バンバン使っていきたいところです。

公式のやりかたはこちらのドキュメントです。
以下のソースコードのようにAWSAppSyncClientというライブラリを使っていて分かりづらい。
apollo-linkを直接使ったほうがブラウザ側だけでなくサーバ側アプリにも使えて可搬性が高い。
なので単なるapollo-linkだけを使ったNode.jsアプリからAppSyncにアクセスしたいです
なので、そういう事例を作ってみます。

読みづらい公式サンプル.js
const AWSAppSyncClient = require('aws-appsync').default;

// Set up Apollo client
const client = new AWSAppSyncClient({
    url: url,
    region: region,
    auth: {
        type: type,
        credentials: credentials,
    }
    //disableOffline: true      //Uncomment for AWS Lambda
});

client.hydrated().then(function (client) {
    //Now run a query
    client.query({ query: query })
    //client.query({ query: query, fetchPolicy: 'network-only' })   //Uncomment for AWS Lambda
        .then(function logData(data) {
            console.log('results of query: ', data);
        })
        .catch(console.error);
});

AppSyncで少し遊んで原理を確認

結局、いろいろみても、

  • jQueryを使った事例にもあるように、AppSyncに単なるjQueryのAjaxでもアクセスできています。
  • AWSAppSyncClientは単なるapollo-clientのラッパですと公式に書いてあります。

本当は難しくないはずなのです。

怖がらなくても、AppSyncは単なるAPI_KEY認証のGraphQLサーバ

AppSyncでのAPIの作り方は、Qiita記事を参考にするとすぐにできます。

作ったAPIの管理画面から「Download configs」をクリックするとこんなファイルがダウンロードできます。

FireShot Capture 32 - AWS AppSync Console_ - https___console.aws.amazon.com_appsync_home.png

ダウンロードしたaws-exports.jsファイル

aws-exports.js
const awsmobile =  {
    "aws_appsync_graphqlEndpoint": "https://***************.appsync-api.**********.amazonaws.com/graphql",
    "aws_appsync_region": "*************",
    "aws_appsync_authenticationType": "API_KEY",
    "aws_appsync_apiKey": "*******************",
};

export default awsmobile;

中身にはAPI_KEYなどが入っています。
このAPI_keyが使えればいいわけです。

ひとまず、InsomniaというAPIテストツールから実行してみます。
URLには上記でダウンロードしたconfig内のURL、X-Api-Keyにはconfig内のapiKeyを設定して、クエリを実行すると、下のようにAPIにアクセスできました。

2018-12-29.png

API_KEY認証はapollo-linkのheadersでできます

X-Api-Keyというヘッダを付ければ動く、ということがわかれば、あとはapollo-linkがそれに対応するかどうかですが、
むろんapollo-linkは対応しています。
こんな風にHttpLinkのコンストラクタにheadersを入れて好きにヘッダを書き込めばいいです。

apollo-link出の書き方.ts
new HttpLink({
  uri: URL, 
  headers: {
    'X-ヘッダの名前': ヘッダの値
  }
})

本編:apollo-linkを使ったアクセスの実装

今回は、Node.jsのアプリでAppSyncにアクセスします。
アプリのソースコードのフォルダで作業します。

まず、先ほどAPI管理画面の「Download configs」からダウンロードした下記のaws-exports.jsをアプリのフォルダに入れます。

aws-exports.js
const awsmobile =  {
    "aws_appsync_graphqlEndpoint": "https://***************.appsync-api.**********.amazonaws.com/graphql",
    "aws_appsync_region": "*************",
    "aws_appsync_authenticationType": "API_KEY",
    "aws_appsync_apiKey": "*******************",
};

export default awsmobile;

アプリのファイルindex.jsにインポートします。

index.js
const aws_exports = require('./aws-exports').default;

さいごに、apollo-linkで上記設定を使ってLinkを作ります。

index.js
const { HttpLink } = require('apollo-link-http');
//もしくはimport { HttpLink } from 'apollo-link-http';
const fetch = require('node-fetch');
const uri = aws_exports.aws_appsync_graphqlEndpoint,
const apiKey = aws_exports.aws_appsync_apiKey;
const link = new HttpLink({uri, fetch, headers: {
  'X-Api-Key': apiKey
}});

このLinkを使ってAppSyncにクエリを投げます。

実装例

私はNode.jsを使って、graphql-toolsのリモートスキーマを作成しAppSyncの結果をそのままフォワードするアプリを作りました。

index.js
import {makeRemoteExecutableSchema, mergeSchemas, introspectSchema} from 'graphql-tools';
const fetch = require('node-fetch');
const { HttpLink } = require('apollo-link-http');
const { ApolloServer, gql } = require("apollo-server-express");
import serverless from "serverless-http";
import express from "express";

const aws_exports = require('./aws-exports').default;

const createSchema = async () => {
    const createRemoteSchema = async (uri, apiKey) => {
        const link = new HttpLink({uri, fetch, headers: {
            'X-Api-Key': apiKey
        }});
        return makeRemoteExecutableSchema({
            schema: await introspectSchema(link),
            link
        });
    };


    const citySchema = await createRemoteSchema(
        aws_exports.aws_appsync_graphqlEndpoint,
        aws_exports.aws_appsync_apiKey);
    return citySchema
};

const run = async () => {
    const schema = await createSchema();

    const app = express();
    const server = new ApolloServer({ schema });
    server.applyMiddleware({ app });
    app.listen({ port: 4000 }, () =>
    console.log(`Server ready at http://localhost:4000${server.graphqlPath}`)
    );
}

run()

AWS Lambdaでも動く

最後のrun()以降を下記に変えると、AWS Lambda上でもちゃんと動きました

index.js
const createServer = (schema) => {
    const app = express();
    const server = new ApolloServer({ schema });
    server.applyMiddleware({ app });
    return serverless(app);
};

let sls
exports.graphqlHandler = async (event, context) => {
    if(sls == null) {
        const schema = await createSchema();
        sls = createServer(schema);
    } else {
        console.log("Already initialized")
    }
    return await sls(event, context);
}

まとめ

AppSyncのGraphQLにアクセスするアプリを作るため、apollo-linkを使った実装例を示しました。
Node.jsサーバアプリとしても動きますし、ちょっと変えればAWS Lambdaでも動きます。

AppSyncだけではちょっと難しい複雑な処理をLambda上でやらせるときに使えそうです。
使ってみてください。

16
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
10