SAM Local (Beta)が発表されローカル環境でサーバレスアプリケーションをデバッグできるようになったので試してみました。
ちなみにリンク先の記事はそのままでは動かそうとすると情報が足りなかったので、試したい人はGitHubの方のチュートリアルやサンプルを触ってみるのが良いと思います。
ローカルにLambdaを作成
チュートリアル用のHelloWorld関数をローカルに作ってみます。
template.yml
AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: A simple Hello World Serverless project Resources: HelloWorld: # <-- 関数の論理ID Type: AWS::Serverless::Function Properties: Runtime: nodejs6.10 Handler: index.handler |
index.js
exports.handler = (event, context, callback) => { console.log('LOG: Name is ' + event.name); callback(null, "Hello " + event.name); } |
event.json
{ "name": "Yuto" } |
実行結果
# `HelloWorld` は関数の論理ID $ sam local invoke HelloWorld -e event.json ...(省略)... "Hello Yuto" |
HelloWorldをAPI Gatewayに対応させる
sam local start-api でAPI Gatewayが起動しますが、上の設定のまま実行するとAPIの定義が足りなくてエラーになります。
$ sam local start-api ...(省略)... ERROR: None of the Serverless functions in your SAM template have valid API event sources. |
Lambda関数の設定に
Events を追加します。
Type: Api でAPI GatewayのAPIの定義になります。
...(省略)... HelloWorld: Type: AWS::Serverless::Function Properties: Runtime: nodejs6.10 Handler: index.handler Events: Api: Type: Api Properties: Path: /hello Method: get |
Events の設定を追加すると Path に指定したpathにAPI Gatewayがデプロイされます。
$ sam local start-api ...(省略)... Mounting index.handler (nodejs6.10) at http://127.0.0.1:3000/hello [GET] |
APIを呼ぶとLambda関数が呼ばれるのですが以下のエラーが出ます。
$ curl http://localhost:3000/hello ...(省略)... ERROR: Function HelloWorld returned an invalid response (must include one of: body, headers or statusCode in the response object) |
API GatewayのProxy Integrationを使用しているため
statusCode がないとエラーになるそうです。
レスポンスに
statusCode を追加します。
exports.handler = (event, context, callback) => { console.log('LOG: Name is ' + event.name); // callback(null, "Hello " + event.name); callback(null, { statusCode: 200, body: "Hello " + event.name }); } |
ここまでで実行には成功しますが event.name が undfined となってしまいます。
$ curl http://localhost:3000/hello Hello undefined |
APIにパラメータを渡す
curlで渡したデータはAPI Gatewayのイベントでラップされるので、API Gatewayのイベントをパースして使用する必要があります。
post も使いたい場合はAPIの定義を
get から
any に変更します。
get と
post を両方マッピングする方法が見つからなかったので。
(2個定義すれば良いのかもですが今回はお試しなので簡単にanyで)
...(省略)... Api: Type: Api Properties: Path: /hello Method: any |
ソースコードもGET/POSTの両方に対応するよう修正します。
const parse_event = { "GET": (event) => event.queryStringParameters, "POST": (event) => JSON.parse(event.body) } exports.handler = (event, context, callback) => { const $event = parse_event[event.httpMethod](event); console.log('LOG: Name is ' + $event.name); callback(null, { statusCode: 200, body: "Hello " + $event.name }); } |
$ curl http://localhost:3000/hello?name=Yuto Hello Yuto $ curl -d '{"name": "Yuto"}' http://localhost:3000/hello Hello Yuto |
まとめ
ホットリロードはソースの更新の度に行われるのではなくAPIの呼び出し毎にソースを読み込み直しているような動きをしているのでそこまでサクサク開発できないんじゃないかなという印象です。
サーバレスのアプリケーションをローカルでデバッグできるだけで楽といえば楽ですが、呼び出しに5秒くらいかかるので1画面で複数のAPIを呼び出すような場合は結構待たされると思います。
また、ホットリロードによりLambda関数のソース変更は再起動不要ですが、MethodをGETからPOSTに変更してみましたが反映されなかったのでAPIの定義を更新するには再起動が必要みたいです。
この記事を書いた人
最近書いた記事
- 2021.12.10React NativeでWallet風UIを実装する
- 2018.11.19Elasticsearchで簡単な検索とscoreを調整する方法
- 2018.10.05ECSをEC2からFargateに切り替える際の注意点
- 2018.09.12AKB48グループ映像倉庫のWeb版をリリースしました