こんにちは!ぽち@pchwです!
AWS Lambdaは気軽に処理が書けて,API Gatewayと組み合わせるAPIサーバを作るのにとても便利です.
色々とサービスを作っていると,HTTPのエンドポイントを叩くと,画像が返ってきて欲しいケースなどが出てきます.(例えば,画像のURLを投げるとバックエンド側で画像を取得して加工を施して返すなど)
お行儀のいい方法であれば,処理を行ったあとにAWS S3にアップロードし,APIレスポンスはそのURLが格納されたjsonが返り,クライアント側がそのURLに対して取得しに行くというのが筋な気がしますが,そんなに大した画像処理をせずに大量の人が使う可能性がある時などに「そのまま画像を返したいな〜」となることがあります.
やっていきましょう.
まず,めんどくさいので,Serverless Frameworkで雛形を作ります.
$ serverless create --template aws-nodejs
$ more handler.js module.exports.hello = (event, context, callback) => { const response = { statusCode: 200, body: JSON.stringify({ message: 'Go Serverless v1.0! Your function executed successfully!', input: event, }), }; callback(null, response); };
デフォルトの handler.js
の処理は, message
と input
というキーを持ったJSONを返す造りになっています.
単純に考えれば,ここに読み込んだ画像のBufferを入れればいいんじゃないか?と思います.
しかし,callback
の第二引数に渡すものはJSON.stringify
していることから分かるように,文字列でないといけません.
なら.toString()
だ!という考えになりますよね?
module.exports.hello = (event, context, callback) => { const fs = require('fs'); fs.readFile('./assets/noimage.png', (err, image) => { const response = { statusCode: 200, body: new Buffer(image).toString('base64') }; callback(null, response); }); });
しかし,これでも上手くいきません.
どうすれば良いかとというと,
- ちゃんと画像を返すということをヘッダーに書く必要がある
- API Gatewayの設定で画像を返すという設定をしないといけない
の二点が追加で必要です.
module.exports.hello = (event, context, callback) => { const fs = require('fs'); fs.readFile('./assets/noimage.png', (err, image) => { const response = { statusCode: 200, headers: { 'Content-Type': "'image/png'", }, body: new Buffer(image).toString('base64'), isBase64Encoded: true }; callback(null, response); }); });
これで処理はOKです.
API Gatewayの方はAWS Consoleでも可能ですが,Serverless Frameworkのプラグインを使うのが楽です.
$ npm install serverless-apigw-binary --save-dev
でプラグインをインストールし,serverless.yml
を編集します.
plugins: - serverless-apigw-binary # for custom.apigwBinary
でplugins
セクションに追加し,custom
セクションで設定を記述します.
custom: apigwBinary: types: #list of mime-types - 'image/*' - 'text/html'
あと,ルートにアクセスされたら画像を返すようにHTTPエンドポイントの設定も記述しておきましょう.
functions: hello: handler: hello timeout: 15 events: - http: path: / method: get
これで $ serverless deploy
すればAPI Gatewayの設定が行われて,バイナリを返せるようになります.
あとはクライアント側で
<img src="DeployしたやつのURL" alt="image"/>
のようにすれば画像が読み込まれるはずです.
画像返すAPIバンバン作っていきましょう!