LoginSignup
0
0

More than 3 years have passed since last update.

[AWS] Lambda + API Gateway でサーバーレスWeb APIを作る ①Lambdaファンクション篇

Last updated at Posted at 2021-03-03

2021/03時点での情報です。AWSのコンソール画面や仕様は頻繁に変更されるので注意してください。

AWSのサービスであるLambdaとAPI Gatewayを使ってサーバーレスのWeb APIを作成したので備忘録として手順をまとめておきます。
間違えていたら教えていただけるとありがたいです。

ゴール

AWS LambdaとAmazon API Gatewayを利用してHTTPプロトコルのGET/POSTで呼び出せる単純なWeb APIを作成すること。

やらないこと

  • AWS自体や他のサービスの説明
  • 最低限のコード以外の実装

APIの仕様

パラメーターの値を簡単に加工して返すだけのシンプルなAPIです。

GET/POST共通

パラメーター名
name 名前を入力します
age 年齢を入力します。

レスポンス

// nameとageにはパラメーターで渡した値が代入されます。
{
  "answer": "My name is ${name}, I am ${age} years old."
}

AWS Lambdaとは

AWS Lambda はサーバーレスコンピューティングサービスで、サーバーのプロビジョニングや管理、ワークロード対応のクラスタースケーリングロジックの作成、イベント統合の維持、ランタイムの管理を行わずにコードを実行できます。Lambda を使用すれば、実質どのようなタイプのアプリケーションやバックエンドサービスでも管理を必要とせずに実行できます。コードを ZIP ファイルまたはコンテナイメージとしてアップロードするだけで、Lambda はあらゆる規模のトラフィックに対して、自動的かつ正確にコンピューティング実行能力を割り当て、受信リクエストやイベントに基づいてコードを実行します。コードは、140 の AWS のサービスから自動的にトリガーするよう設定することも、ウェブやモバイルアプリケーションから直接呼び出すよう設定することもできます。Lambda 関数をお気に入りの言語 (Node.js、Python、Go、Java など) で記述し、サーバーレスツールと AWS SAM や Docker CLI などのコンテナツールの両方を使用して、関数をビルド、テスト、デプロイできます。(公式より

だいたいこんな感じ

  • サーバーを建てないでコード(関数)を実行できるよ
  • コードはいろんな言語で書けるよ
  • 勝手に適切なCPUリソースを割り当ててくれるよ
  • アプリケーションや他のAWSのサービスから作成した関数を呼び出せるよ

単一の関数をアップロードして独立して実行できるサービスです。

Amazon API Gatewayとは

フルマネージド型サービスの Amazon API Gateway を利用すれば、開発者は規模にかかわらず簡単に API の作成、公開、保守、モニタリング、保護を行えます。API は、アプリケーションがバックエンドサービスからのデータ、ビジネスロジック、機能にアクセスするための「フロントドア」として機能します。API Gateway を使用すれば、リアルタイム双方向通信アプリケーションを実現する RESTful API および WebSocket API を作成することができます。API Gateway は、コンテナ化されたサーバーレスのワークロードやウェブアプリケーションをサポートします。

だいたいこんな感じ

  • 外部からHTTPプロトコルを通じてサービスを呼び出せるURLを作成してくれるよ
  • 受け取ったリクエストを他のサービスに渡してくれるよ
  • バージョン管理やモニタリングとか色々できるよ

今回の実装部分

Lambdaファンクションの作成・コードの実装

Lambdaで作成する関数の単位はファンクションです。
ファンクションを作成してコードを実装(もしくはアップロード)します。

ファンクション作成

Lambdaサービスのページから Functions > Create Functionをクリック
Screen Shot 2021-03-02 at 0.19.17.png

  • Author from scratchを選択
  • Function nameにファンクション名を作成
  • Runtimeでコードを書く言語を指定(今回はNode.jsで書きます)
  • Create Functionをクリック

Screen Shot 2021-03-02 at 0.38.24.png

これでファンクションが作成できたので中身を実装していきます。

ファンクションのコード実装

今回はコンソールで直接コードを書きます。

Designerでファンクション名を選択してください。
Screen Shot 2021-03-02 at 0.41.18.png

すると下にFunction codeエリアが現れるのでここにコードを書いていきます。
Screen Shot 2021-03-02 at 0.44.15.png

GETの(クエリパラメーターを受け取る)場合の実装

HTTPリクエストをGETで受け取った場合、API Gatewayから渡されるevent変数のqueryStringParametersにクエリパラメーターが格納されています。
なのでまずはGETリクエストを受け取った際のコードを実装してみます。

exports.handler = async (event) => {
    const name = event.queryStringParameters.name
    const age = event.queryStringParameters.age

    return {
        "statusCode": 200,
        "headers": {
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Methods": "GET"
        },
        "body": `{ "answer": "My name is ${name}, I am ${age} years old." }`,
        "isBase64Encoded": false
    }
}

ポイントは先程言ったとおりevent.queryStringParametersからパラメーターが取得できるというところと、レスポンスの形式です。

後ほど紹介しますが、API GatewayとLambdaの連携方法としてLambdaプロキシ統合という方法を使用します。
この方法で連携する場合にはレスポンスは以下の形式で返す必要があります。

{
  "isBase64Encoded" : "boolean",
  "statusCode": "number",
  "headers": { ... },
  "body": "JSON string"
}

デプロイ・テスト

コードを実装したらDeployを押してください。
コードがデプロイされて実行可能になります。

それではテストパラメーターを設定してテストを行います。
Testボタンを押します。

Screen Shot 2021-03-02 at 1.22.07.png

  • Configure test eventが開きます。

  • Create new test eventを選択してイベント名を指定、パラメーターを入力します。(スクショではすでに作成済みなのでEdit saved test eventsが選択されています。)

プロキシ統合の形式に合わせてパラメーターを指定します。

success
{
    "queryStringParameters": {
        "name": "Akumachan",
        "age": "100030"
    }
}

Createを押してポップアップが閉じたら再度Testを押してテストを実行します。

Screen Shot 2021-03-02 at 1.36.23.png

実行結果が表示されました。イージー!

POSTの(リクエストボディを受け取る)場合の実装

HTTPリクエストをPOSTで受け取った場合、API Gatewayから渡されるevent変数のbodyにクエリパラメーターが格納されています。
event.bodyは文字列形式で格納されているようなのでJSONでリクエストボディを送信している場合はJSON.parseしてパラメーターにアクセスします。

と、その前にメソッドによって処理を変えるコードを挿入します。
メソッドの種類はevent.httpMethodに格納されているのでメソッドごとに分岐します。

※(2021/03/06)下記コード修正しました。API GatewayでHTTP APIを作成した場合とREST APIを作成した場合でevent内のHTTPメソッドが書いてある場所が違いました。HTTP APIの場合はevent.requestContext.http.methodで、REST APIの場合はevent.httpMethodのようです。

index.js
exports.handler = async (event) => {
    let name, age

    if ([event.httpMethod, event.requestContext.http.method].includes('GET')) {
        name = event.queryStringParameters.name
        age = event.queryStringParameters.age

    } else if ([event.httpMethod, event.requestContext.http.method].includes('POST')) {
        // Return response for POST request
    } else {
        // Return error.
    }

    return {
        statusCode: 200,
        body: `{ "answer": "My name is ${name}, I am ${age} years old." }`,
    }
}

それではPOSTリクエストボディからパラメーターを取り出してnameageに代入します。

index.js
exports.handler = async (event) => {
    let name, age

    if ([event.httpMethod, event.requestContext.http.method].includes('GET')) {
        name = event.queryStringParameters.name
        age = event.queryStringParameters.age

    } else if ([event.httpMethod, event.requestContext.http.method].includes('POST')) {
        const body = JSON.parse(event.body)
        name = body.name
        age = body.age
    } else {
        // Return error.
    }

    return {
        statusCode: 200,
        body: `{ "answer": "My name is ${name}, I am ${age} years old." }`,
    }
}

レスポンスの形式は共通のコードなので、これでテストを実行してみましょう。Deployを押してデプロイを完了してください。

テスト

Testの横の▼をクリックしてConfigure test eventをクリック、Create new test eventからパラメーターを指定します。

successPOST
{
  "httpMethod": "POST",
  "body": "{\"name\": \"AkumachanPOST\",\"age\": \"100032\"}"
}

Createボタンを押してポップアップが閉じたらTestをクリックして実行します。

Screen Shot 2021-03-03 at 22.53.56.png

これでPOSTリクエストからのリクエストも処理できるようになりました。

次回に続く。

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