0
0

More than 3 years have passed since last update.

Serverless FrameworkでLambdaにGraphQL APIを立てる

Last updated at Posted at 2020-12-05

基本的にはこちらを参考にしました。
How to Make a Serverless GraphQL API using Lambda and DynamoDB
https://www.serverless.com/blog/make-serverless-graphql-api-using-lambda-dynamodb

ただし、イベントハンドラをasync関数にしたり、GETリクエストではなくPOSTリクエストを受け付けるようにしています。
また、上記では、GraphQLSchema()などを使っていますが、スキーマの定義などに関しては、GraphQL.js公式ページを参考にしました。
Getting Started With GraphQL.js
https://graphql.org/graphql-js/

あれ、「How to Make a Serverless GraphQL API」の方、ほとんど参考にしてない?笑

結論

特に難しいことはなく、POSTリクエストで送った値をevent.bodyから取り出して、graphql()の第二引数に渡すだけ。

コマンドやコード

$ sls create -t aws-nodejs-typescript -p sample-graphql-lambda-api
$ yarn init -y
$ yarn
$ yarn add graphql
serverless.ts
// 下記追加
// その他、region(ap-northeast-1など)を追加するのを忘れずに。
  functions: {
    query: {
      handler: "handler.query",
      events: [
        {
          http: {
            method: "post",
            path: "graphql",
          },
        },
      ],
    },
  }
handler.ts
//import { APIGatewayProxyHandler } from "aws-lambda";
import "source-map-support/register";
import {
  graphql,
  buildSchema
} from "graphql";

const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

const root = {
  hello: () => {
    return "Hello world!";
  },
};

export const query = async (event) => {
  const query = event.body;
  const result = await graphql(schema, query, root);
  const response = {
    statusCode: 200,
    body: JSON.stringify(result),
  };
  return response;
};
$ curl --request POST --header "Content-Type: application/json" --data "{ hello }" '{Lambda関数のエンドポイント }}'

{"data":{"hello":"Hello world!"}}

おしまい。

[番外編]リゾルバーで引数を取り出す時の{ person }ってなんだ?

引数を足したり、複数のデータを返す場合。

handler.ts
const schema = buildSchema(`
  type Query {
    hello(person: String): Text
  }
  type Text {
    text1: String,
    text2: String
  }
`)

const root = {
  hello: ({ person }) => {
    return { text1: `${person}さん、こんばんは!!!!!!!!!!`, text2: "おはようございます" }
  }
}
$ curl --request POST --header "Content-Type: application/json" --data "{ hello(person: \"tarou\"){text1 text2 }}" '{Lambda関数のエンドポイント }'

{"data":{"hello":{"text1":"tarouさん、こんばんは!!!!!!!!!!","text2":"おはようございます"}}}

rootオブジェクトにクエリごとに設定する関数で引数を取り出す時、なんでpersonではなく{ person }なのかと思っていた。

これはJSの記法で、分割代入らしい。

var origin = {a:1, b:2, c:3};
var {a} = origin;
var {b} = origin;
var {c} = origin;
console.log('a = ' + a); // a = 1
console.log('b = ' + b); // b = 2
console.log('c = ' + c); // c = 3
JavaScriptの変数名が中括弧で囲まれた変数宣言

オブジェクトから{}の中で指定したプロパティの値を取り出して、それを同名の変数に代入してるらしい。
つまり、rootオブジェクトでクエリごとに割り振る関数の引数には、オブジェクトが渡されているらしい。
→そういえば、curlでも、--data "{ hello(person: \"tarou\"){text1 text2 }}"という感じで、personkeyを渡していたんだった(これがないとエラーになる)

ちなみに、「rootオブジェクトでクエリごとに割り振る関数」は'resolver function'というらしい。

// The root provides a resolver function for each API endpoint
var root = {
hello: () => {
return 'Hello world!';
},
};
Getting Started With GraphQL.js

番外編が長い。
別途、AppSyncってなんだ?GraphQL使うなら、API Gatewayじゃなくてこっち使った方がいいのかな。

0
0
0

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
0
0