「あぁー」
仕事していると、考えなきゃならないことっていっぱいありますよね。
「あぁー、コールバックをするAPIを作ったけど、そのテストだとか検収作業のためにコールバックの受け口が必要で、できれば手間なくコストあんまりかけることなく、ただただ単純にWebのアクセスログとPOSTされたデータだけを見られるような、そんな一時的な仕組みが割とすぐ欲しいー」みたいなのを考えなきゃならないことが。僕にはよくあります。
こんにちは。バックエンドエンジニアのまさくにです。何も考えたくない。
さて、このような必要が生じたとき、どのような手段を取ればよいのでしょうか。僕が教えて欲しいくらいなのですが、いろんな方法が考えられると思います。Webサーバーが一台あってPHPなんかが動いていれば楽勝ですね。でもこんなちょっとした役割のためのサーバーが見つからない。
じゃあHerokuとかNetlifyとかでどうにかならなんかなーって考えたんですけど、リポジトリ一個用意してデプロイー? 永続データどーすっかなーって考えるとちょっと面倒な気もする。じゃあログかーCloudWatch Logsかなー、Lambdaかなー、というのが以下の方法です。いきましょう。
全体像
簡単ですね。
今回はAPIのコールバックを受けるような用途を想定しているので、どっかからAPI GatewayがPOSTで叩かれ、Lambdaが起動され、CloudWatch LogsにPOSTデータが載るようなものを考えています。認証などは設けないので、秘匿データの扱いにはご注意ください。
Lambda部分
まずLambdaでPOSTデータをCloudWatch Logsに書き出すスクリプトを書いておきます。LambdaはデフォルトでCloudWatch Logsにログを書き出すようになっているので、IAM設定する必要はありません。(自動で作ってくれます)下記のようにLambdaを作ります。
この条件で作成し、あとはFunctionを書いておきます。今回はNode.js 8.1.0を選んでいるので下記のように。eventの中の body-json にPOSTデータが入ってくるのですが、これは後で設定します。それにしてもconsole.logでCloudWatch Logsに入れてくれるのはとても楽ですね。
exports.handler = (event, context, callback) => {
console.log("callback response " + JSON.stringify(event['body-json']));
callback(null, {"message":"seikou_daze"});
};
ここまで書いたら右上の「保存」で保存しておきましょう。一応「テストイベントの作成」からテストを作って、実行してみると下記のようになります。ちゃんと動いているようです。
まだデータが入ってきていないので、ログ出力の部分で「callback response undefined」となっていますが、これをAPI Gatewayとつなげてログ出力できるようにします。
API Gateway部分
上記のように新しくAPI Gatewayを作りましょう。
リソースを作成しときます。API Gatewayでリソースというのは要するにURLを追加するということになります。このURLにアクセスすることでLambdaを起動させるということですね。下記では /reciever というリソースを追加しています。
で、このリソースに対してメソッドの追加もしておきます。今回はデータを送るのでPOST。Lambda関数に先ほど作成した関数を設定しておきましょう。
この時点で、テストをすると下記のようにLambdaからレスポンスが帰ってくると思います。テストでLambdaとの疎通が確認できたら、一度デプロイしてしまいましょう。下記のようにステージを適当に作成し、デプロイを行います。
これでAPI Gateway用のURLが発行されるので、POSTができるようになります。何を使ってもいいんですが、下記のようなコマンドでPOSTしてみましょう。
$ curl -X POST -H 'Content-Type: application/json' -d '{"hey": "yo!"}' https://xyz.execute-api.ap-northeast-1.amazonaws.com/test-receiver-999-105/receiver
{"message":"seikou_daze"}
ちゃんとLambdaからレスポンスが帰ってきているのが確認できますね。でもこれだけだとCloudwatch Logsには何も書かれません。「callback response undefined」のままだと思います。POSTデータを渡すには、API Gatewayでもう少し設定が必要です。
もう一度API GatewayのPOSTメソッドを開き、「統合メソッド」を開いてください。その「マッピングテンプレート」を下記のように設定します。
{
"body-json" : $input.json('$')
}
これで保存すれば設定完了です。何をしてるかというとAPI GatewayはLambdaを起動するのですが、デフォルトでPOSTデータなどを渡しません。それを渡すためのマッピングを書く必要があり、上記の設定を行うことで body-json にデータが入るようになります。
試してみる
もう一度curlで実行してみます。ちなみにapplication/jsonだった時のマッピングテンプレートを書いたので Content-Type で指定しないとLambdaにデータが渡りません。
curl -X POST -H 'Content-Type: application/json' -d '{"hey": "yo!"}' https://xyz.execute-api.ap-northeast-1.amazonaws.com/test-receiver-999-105/receiver
{"message":"seikou_daze"}
Cloudwatch Logsを見ましょう。ログストリームに下記のようなログが入ってくるのではないでしょうか。
やったぜー! 成功だぜー! 無料枠だぜー! という感じで目的を達することができました。でも絶対にもっと簡単にできる気がするので、皆さまからのグッドアイデアお待ちしてます。まさくにでした。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。