東京アメッシュの画像を返すaws lambdaを作る
経緯
以前数年間いた現場ではSlackを主にコミュニケーションのツールとして活用していて、チャットボックスに
ueo ame
とやると最新の東京アメッシュの画像を返す連携機能がありました。
何気に便利だったのと新しい現場でもslackがメインで使用されているようなので自分でもやってみようと思い実際にやってみました。
aws lambdaも使ってみたかったというのもあり、実際にやってみると結構面倒だったの記録も含めてメモ。
環境
- aws lambda上のNodeJS
- TypeScript
Lambdaコード
実際に東京アメッシュの画像を取得する処理はnpmライブラリに任せるようにして、Lambda関数では取得した画像をJpegフォーマットで画質を落として画像サイズを小さくする処理を追加しました。
デフォルトだと400〜500KBになりますが、JPEGで品質を80%くらいにすると100KB前後までファイルサイスを小さくすることが出来ました。
npm i tokyo_amesh_node_client
lambda関数(TypeScript)
import { AmeshClient, ImageSize } from "tokyo_amesh_node_client";
import * as Jimp from "jimp";
const handler = async (event: any, context: any, callback: any) => {
try {
let img = await AmeshClient.getLatestImage(ImageSize.Small);
img
.quality(80)
.getBuffer(Jimp.MIME_JPEG, (err, buf) => {
if (!!err) {
callback(err, null);
return;
}
let res = buf.toString("base64");
callback(null, res);
});
} catch (ex) {
callback(ex, null);
}
};
export {
handler,
}
Lambdaの雛形に従って、エラーならエラーを、正常だったらアメッシュ画像を返しています。
ポイントはbase64エンコードしているところでしょうか。
Lambdaでバイナリを返す場合は関数側はこのようにする必要があるようです。
詳細はこちらのドキュメントに書いてあります。
Enable Support for Binary Payloads in API Gateway
ソースをS3にアップ
何だかんだでnode_modulesを含めるとファイルサイズが大きくなってしまい直接アップロードは出来なかったのでzipで固めてS3にアップロードすることにしました。
aws lambda consoleで関数を設定
こんな感じでしょうか。
TypeScriptのトランスパイル先ディレクトリがdistなのでハンドラには dist/amesh.handler としています。
api gatewayの設定
設定したLambda関数をAPIとして呼び出せるようにします。awsのAPI Gatewayの管理画面を開いて手順に従って進めます。
名前の設定
まずはAPIの名前をつけます。今回はamesh-apiという名前にしました。
リソースを作成
とりあえずget-imageという名前で作成。
アクションの設定
作成したリソースに対してgetアクションを設定。
Lambda関数の割当
作成したLambda関数のあるリージョンと、Lambda関数を指定。
メソッドレスポンスの変更
メソッドレスポンスをこんな感じに設定。
統合レスポンスの変更
統合レスポンスをこんな感じに設定。
コンテンツの処理を「バイナリに変換」にするのを忘れないでください。
テスト
この状態でテストを実行。
base64エンコードされたものが返ってきているようなのがわかります。
デプロイ
最後にアクションメニューから"APIのデプロイ"を選択して実行すれば、外部からHTTPでたたけるようになります。
確認
エンドポイントが表示されるのでリンクをクリックするとちゃんと画像が表示されました。
おしまい
実際にやってみると画像が汚かったりなんか色々不安定でした。
Lambdaのメモリを増やしたりもしましたが品質が安定しなかったので、最終的にLambdaではやらないことになりそうです、、、。