
はじめに
こんにちは~、BFT名古屋支店の猫です。季節の変わり目のせいか、毎日眠いです。
そんな眠たい時でもできるのが、そう、検証!
ということで、"RESTful APIの構築" をやってみました。
使用したのは「Amazon API Gateway」「AWS Lambda」「Amazon RDS」の3つです。
これらを選択した理由は、業務で扱ったことがあり取り組みやすかった&ざっと調べた感じ情報が色々落ちてそうと思ったためです。ありがとうインターネット!
今回はLambdaの実装部分を中心にご紹介します。
「API GatewayとLambdaの連携が上手くいかない」「LambdaとRDSの連携が上手くいかない」といった方の参考になればと思います。
この記事を読むのにあるといい知識
API Gateway と Lambda の作成・連携手順
bftnagoya.hateblo.jp
APIの概要
ここでは作ったAPIの構成や機能についてご紹介します。
あまり興味ない方は飛ばしていただいてOKです。
今回は、「料理のレシピを登録・更新・削除・閲覧できるAPI 」を作りました。理由は特にありません。
構成
誰が何をしているのかを簡単にご説明します。
Amazon API Gateway
ユーザからのリクエストを受け取って、中間処理を実行し、ユーザにレスポンスを返します。
中間処理は、リソース(ex:/recipes, /recipes/{id})やメソッド(ex:GET, POST, DELETE, …)ごとに定義することができます。今回の構成ではLambdaを呼び出します。実際の画面 AWS Lambda
API Gatewayから呼び出されると、所定の処理を実行し、結果をAPI Gatewayに返します。
今回作成したLambdaでは「リクエストに応じてSQL文を生成し、RDSに対してクエリを実行する」という処理を実行します。Amazon RDS
登録されているデータ(=料理のレシピ)を持っています。
Lambdaから投げられたSQL文を実行し、その結果をLambdaに返します。
機能
どんな機能があるのか簡単にご説明します。
データベース処理として一般的なCRUD(Create, Read, Update, Delete)の機能を実装しています。
登録機能
レシピをデータベースに登録する更新機能
idで指定されたレシピを更新する削除機能
idで指定されたレシピを削除する閲覧機能(全レシピ)
データベースに登録されているすべてのレシピを表示する閲覧機能(id指定)
idで指定されたレシピを表示する
Lambdaの実装
ではさっそく実装したコードを紹介していきます。
実装のポイントは以下の二点です。
これらについて、詳しくははまた別の記事にまとめたいと思いますので
今日のところは(ふ~ん、こんな書き方するんだ~)くらいに思っていただければと思います。
使用環境
登録機能
レシピをDBに登録する機能です。
リクエストbodyで指定されたレシピをDBに登録し、登録できた場合はそのレコードを、登録できなかった(リクエストの形式がおかしかったなど)場合はエラー文を返します。
大まかな流れは以下の通りです。
1. DB接続
2. レコード登録
3. レコード取得(登録したレコードを取得)
4. レスポンス生成
更新機能
DBに登録されているレシピを更新する機能です。
リクエストのパスパラメータで指定されたidのレコードに対して、 リクエストbodyで指定された項目の値を更新します。
更新できた場合はそのレコードを、更新できなかった(指定されたidのレコードが存在しないなど)場合はエラー文を返します。
大まかな流れは以下の通りです。
1. DB接続
2. 存在確認(指定されたidのレコードがDBに存在するか確認)
3. レコード更新
4. レコード取得(更新したレコードを取得)
5. レスポンス生成
削除機能
DBに登録されているレシピを削除する機能です。
リクエストのパスパラメータで指定されたidのレコードをデータベースから削除します。
削除できた場合はその旨を伝えるメッセージを、削除できなかった(指定されたidのレコードが存在しないなど)場合はエラー文を返します。
大まかな流れは以下の通りです。
1. DB接続
2. 存在確認(指定されたidのレコードがDBに存在するか確認)
3. レコード削除
4. レスポンス生成
閲覧機能(全レシピ)
DBに登録されている全レコードを取得する機能です。
取得できた場合はそのレコードを、取得できなかった(レコードが存在しないなど)場合はエラー文を返します。
大まかな流れは以下の通りです。
1. DB接続
2. レコード取得(全レコードを取得)
3. レスポンス生成
閲覧機能(id指定)
先ほどご紹介した「閲覧機能(全レシピ)」のid指定するバージョンです。
リクエストのパスパラメータで指定されたidのレコードのみを取得します。
取得できた場合はそのレコードを、取得できなかった(指定されたidのレコードが存在しないなど)場合はエラー文を返します。
大まかな流れは以下の通りです。
1. DB接続
2. レコード取得(指定されたidのレコードのみを取得)
3. レスポンス作成
使ってみた
できあがったAPIを使ってみました!
今回は画面を作っていないので、curlコマンドを使用してAPIを叩きます。
①まずはデータベースが空っぽであることを確認します。
[myuser@myhost ~]$ curl -X GET https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/my-recipe-prod/recipes | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 15 100 15 0 0 269 0 --:--:-- --:--:-- --:--:-- 272 { "recipes": [] } [myuser@myhost ~]$
データが登録されていないことが確認できました。
②次にデータを登録してみます。
[myuser@myhost ~]$ curl -X POST -H "Content-Type: application/json" -d '{"title":"カレー", "making_time":"40分", "serves":"4人", "ingredients":"肉,玉ねぎ,人 参,スパイス,水", "cost":1000' https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/my-recipe-prod/recipes | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 451 100 322 100 129 767 307 --:--:-- --:--:-- --:--:-- 1076 { "message": "Recipe successfully created!", "recipe": [ { "id": 1, "title": "カレー", "making_time": "40分", "serves": "4人", "ingredients": "肉,玉ねぎ,人参,スパイス,水", "cost": 1000, "created_at": "2022-10-12 05:00:21", "updated_at": "2022-10-12 05:00:21" } ] } [myuser@myhost ~]$
登録が成功したことを示すメッセージが出力されました!
このあと同様に2つほど登録しました。
③登録したデータを見てみます。
こちらは全レシピを閲覧するリクエストとその結果です。
データを3つ登録したので、3つのデータが出力されれば成功です。
[myuser@myhost ~]$ curl -X GET https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/my-recipe-prod/recipes | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 772 100 772 0 0 15858 0 --:--:-- --:--:-- --:--:-- 16083 { "recipes": [ { "id": 1, "title": "カレー", "making_time": "40分", "serves": "4人", "ingredients": "肉,玉ねぎ,人参,スパイス,水", "cost": 1000, "created_at": "2022-10-12 05:00:21", "updated_at": "2022-10-12 05:00:21" }, { "id": 2, "title": "スープ", "making_time": "15分", "serves": "2人", "ingredients": "トマト,ツナ,コンソメ,水", "cost": 300, "created_at": "2022-10-12 05:22:57", "updated_at": "2022-10-12 05:22:57" }, { "id": 3, "title": "だし巻き卵", "making_time": "5分", "serves": "2人", "ingredients": "卵,だし,水", "cost": 150, "created_at": "2022-10-12 05:24:36", "updated_at": "2022-10-12 05:24:36" } ] } [myuser@myhost ~]$
こちらはidを指定してレシピを閲覧するリクエストとその結果です。
指定したレシピのみが出力されれば成功です。
[myuser@myhost ~]$ curl -X GET https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/my-recipe-prod/recipes/1 | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 314 100 314 0 0 758 0 --:--:-- --:--:-- --:--:-- 758 { "message": "Recipe details by id", "recipe": [ { "id": 1, "title": "カレー", "making_time": "40分", "serves": "4人", "ingredients": "肉,玉ねぎ,人参,スパイス,水", "cost": 1000, "created_at": "2022-10-12 05:00:21", "updated_at": "2022-10-12 05:00:21" } ] } [myuser@myhost ~]$
どちらも想定通りに動くことが確認できました!
④続いて、レシピを更新してみます。
最初に登録したレシピのタイトルを「カレー」から「最強カレー」にしてみます。
[myuser@myhost ~]$ curl -X PATCH -H "Content-Type: application/json" -d '{"title":"最強カレー"}' https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/my-recipe-prod/recipes/1 | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 413 100 386 100 27 1047 73 --:--:-- --:--:-- --:--:-- 1119 { "message": "Recipe successfully updated!", "recipe": [ { "id": 1, "title": "最強カレー", "making_time": "40分", "serves": "4人", "ingredients": "肉,玉ねぎ,人参,スパイス,水", "cost": 1000, "created_at": "2022-10-12 05:00:21", "updated_at": "2022-10-12 06:14:48" } ] } [myuser@myhost ~]$
タイトルと更新日時の値が変わっていることが確認できました。
⑤最後に、レシピを削除してみます。 先ほど更新したカレーのレシピのidを指定してリクエストを投げます。
[myuser@myhost ~]$ curl -X DELETE https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/my-recipe-prod/recipes/1 | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 43 100 43 0 0 103 0 --:--:-- --:--:-- --:--:-- 103 { "message": "Recipe successfully removed!" } [myuser@myhost ~]$
削除が成功したことを示すメッセージが出力されました!
再び全レシピを閲覧するリクエストを投げてみると・・・
[myuser@myhost ~]$ curl -X GET https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/my-recipe-prod/recipes/ | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 529 100 529 0 0 1426 0 --:--:-- --:--:-- --:--:-- 1429 { "recipes": [ { "id": 2, "title": "スープ", "making_time": "15分", "serves": "2人", "ingredients": "トマト,ツナ,コンソメ,水", "cost": 300, "created_at": "2022-10-12 05:22:57", "updated_at": "2022-10-12 05:22:57" }, { "id": 3, "title": "だし巻き卵", "making_time": "5分", "serves": "2人", "ingredients": "卵,だし,水", "cost": 150, "created_at": "2022-10-12 05:24:36", "updated_at": "2022-10-12 05:24:36" } ] } [myuser@myhost ~]$
カレーのレシピが削除されていることが確認できました!
おわりに
作業前は3時間くらいで作れるかな~と思っていたのですが、実際には8時間くらいかかってしまいました。
この差分5時間のほとんどは、API Gateway - Lambda間のデータのやり取りを実装するのに費やしました。
API Gateway - Lambdaのやり取りでなんでそんなに苦労したの?という話は次回の記事で書きたいと思いますので、ぜひお楽しみに!
ここまで読んでいただきありがとうございました^^