APIGateway + Lambda(Python)でAPIを作る

APIGatewayとLambda

APIGateWayとは

公式によると、下記のように説明されています。
『フルマネージド型サービスの Amazon API Gateway を利用すれば、デベロッパーは規模にかかわらず簡単に API の作成、公開、保守、モニタリング、保護を行えます』

ざっくり言うと、簡単にAPIを作れるサービスといった感じでしょうか。

Lambdaとは

公式による解説は下記です。
『Lambda はサーバーをプロビジョニングしたり管理しなくてもコードを実行できるコンピューティングサービスです。』

ざっくり言うと、サーバを用意しなくてもプログラムを実行できるサービスです。

EC2やレンタルサーバ等だと、APIで利用するには環境構築して常にサーバを立ち上げておく必要があるのですが、Lambdaではその必要はありません。

APIGateway + Lambdaでできること

LambdaをAPIGatewayを利用することによって、簡単にサーバレスなAPIを実装できます。

サーバを常に起動しておく必要がないので、コストをかなり抑えることができます。

詳細はそれぞれの料金表(公式)をご参照ください。
APIGateWayの料金表
Lambdaの料金表

ざっくり言うとAPIGateWayは3.50USD/100万アクセス、Lambdaは0.20USD/リクエスト100 万件(2022年10月2日現在)です。

いずれにせよ、100万アクセスあたりという計算になるので、個人で普通に使っている分にはほとんど料金は発生しないと思って良さそうです。

実装に作ってみよう

Lambda関数を作る

lamdaの管理画面に移動して、左メニューから「関数」を選択。画面右の「関数の作成」をクリック。

「一から作成」をクリック。

「基本的な情報」の関数名を入力。ランタイムを設定(今回はpythonにする)。
他の設定は触らずに、画面下部の「関数の作成」をクリック。

ちなみに、Lambda関数の初期コードはこんな感じ。
アクセスすると、”Hello from Lambda”を返す挙動です。
(Lambdaのトップ→関数→作成した関数名を選択、で確認できます。)

初期コードのままPOST送信をするとCORSエラーが出ます。


6行目’statusCode’と、7行目’body’の間に以下を追記します。
「アクセス元ドメイン」については、特定のサイトからのみアクセス場合は任意のドメインを、どこからでもアクセスして大丈夫な場合は’*’とします。


※セキュリティー的にはドメインを指定した方が安全です。

'headers': {
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Allow-Origin': 'アクセス元ドメイン',
            'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
        },

APIGatewayを設定して、Lambda関数と連携する。

APIGatewayの管理画面から、REST APIを選択する。

「REST」を選択、「新しいAPI」を選択、API名を設定して、画面右下の「APIの作成」をクリック。

「アクション」、「メソッドの作成」をクリックする

「POST」を選択して、チェックマークをクリック

「Lambdaプロキシ統合の使用」をチェックして、先ほど作成したLamda関数名を入力して、保存。
(他の設定は触らなくて可。この後でてくる権限についての質問は、許可でOK。)

※Lambdaプロキシ統合とは?
API Gatewayに対してLambdaから返される値のフォーマットが指定されます。使いやすいので普通に使う場合には利用した方がいいと思います。 詳細は下記外部サイト様をご参照ください。

API Gateway + Lambda プロキシ結合の使用有無による違い - Qiita
やりたいこと API GatewayとLambdaでREST APIを作成する際には、API Gateway側でLambdaプロキシ統合の使用有無を選べます。 今まであまり気にしていませんでしたが、開発する中で挙動の違いに...

「アクション」から「APIのデプロイ」

デプロイするステージを作成する。「新しいステージ」を選択し、ステージ名を入力して、デプロイ。

これで、APIGateWayの設定は完了です。
遷移先画面で、APIのURLが表示されます。
実際に利用する際には、このURLを指定します。

Lamdaに戻って、先ほど作成した関数を確認すると、APIGatewayとの連携ができていることを確認できます。

実際に試してみる

まずはそのまま試してみる(Hello form Lambda!が返ってくる)

HTMLでフォームを作ってPOST送信します。
ただし、送るデータをjson形式にしてあげたいので、Ajaxを使いましょう。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>lambdaのデモ</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<form>
    <input type="number" id="number1">
</form>
<button>送信する</button>
</body>
</html>

<script>
$(function () {
    $('button').on('click',function () {
      
       //formの値をjsonに変換
       var arr = [$('#number1').val()];
       var submitData = JSON.stringify(arr);
      
        //ajaxで送信する
        $.ajax('ApiGatewayのurl', {
            type: 'post',
            data: submitData,
            dataType: "json",
        }).then(function (data) {
            console.log(data);
        }).fail(function (error) {
            console.log(error);
        })
    });
  });
</script>

「送信する」ボタンをクリックすると、”Hello form Lambda!”が返ってくる

ちょっと改造。足し算した結果を返す

このままでは実用的ではないので、ちょっと改造してみましょう。
「数値を二つ渡すと、足し算して結果を返す」lambda関数を作ります。

HTMLフォームとLambda関数を以下のように修正します

●HTMLコード(部分的に先ほどのコードに追記。12行目、23行目)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>lambdaのデモ</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<form>
    //追加1:formに値を追加
    <input type="number" id="number1">
    <input type="number" id="number2">
</form>
<button>送信する</button>
</body>
</html>

<script>
$(function () {
    $('button').on('click',function () {
      
       //追加2:配列に値を追加
        var arr = [$('#number1').val(),$('#number2').val()];
        var submitData = JSON.stringify(arr);
      
        $.ajax('ApiGatewayのurl', {
            type: 'post',
            data: submitData,
            dataType: "json",
        }).then(function (data) {
            console.log(data);
        }).fail(function (error) {
            console.log(error);
        })
    });
  });
</script>

●Lambdaのコード(全面修正)

import json

def lambda_handler(event, context):
 //ajaxで送られた値を受け取る
    body = event["body"]

   //jsonを辞書に変換
    numbers = json.loads(body)
    
 //辞書の値を取得
    number1 = numbers[0]
    number2 = numbers[1]
    
 //足し算
    num = int(number1) + int(number2)
    
    return {
        'statusCode': 200,
         'headers': {
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Allow-Origin': '任意のドメイン',
            'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
        },
        'body': num
    }

↑のlambdaコードをデプロイします。

実際に試してみた様子です。うまくいっているようですね。

とまあ、こんな感じで利用できます。
jsonで値を渡して、json.loadsで読み込んであげる等、ちょっと工夫が必要です。

参考サイト

Amazon API Gateway で AWS Lambda を使用する(AWS公式の解説)

API Gatewayとlambdaを使ってみる(Getの場合のAPI構築)

API Gateway + Lambda プロキシ結合の使用有無による違い(プロキシ統合についての解説)

コメント

タイトルとURLをコピーしました