この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
好物はインフラとフロントエンドのかじわらゆたかです。
Amazon API Gatewayのノウハウがいろいろ出ているので、 ブラウザから動かして見ようと思います。
流れとしてはAWS Lambdaで、S3 Pre-Signed URLの生成を実装し、 それをAmazon API Gatewayにデプロイします。
その後、ブラウザからデプロイされたAPIを実行し、 生成されたS3 Pre-Signed URLからアップロードされた画像を取得するといった形になります。
Pre-Signed URLの生成
AWS SDKを用いて、Presigned-URLを発行します。 AWS Gateway自体はTokyoリージョンには来ていませんが、 取得するS3のオブジェクトはTokyoリージョンから取得するといったケースで実装してみます。
app.js
'use strict';
var AWS = require('aws-sdk');
var bucket = 'cm-kajiwara-image';
var region = 'ap-northeast-1';
var s3 = new AWS.S3({
'region': region
});
var key = 'classmethod-icatch.png';
var params = {
Bucket: bucket,
Key: key,
Expires: 60
};
exports.handler = function(event, context) {
s3.getSignedUrl('getObject', params, function(err, url) {
if(!err){
context.done(null,url);
}
});
};
以前紹介したAWS Lambda Functionをローカルで動かすdriver.jsを用い、 問題なく動くことを確認します。
$ node ./driver.js
https://cm-kajiwara-image.s3-ap-northeast-1.amazonaws.com/classmethod-icatch.png AWS Access Key)&Expires=1436681110&Signature=(generated Signature)
今回Lambdaパッケージを作成するに辺り、 以下のページのサンプルプロジェクトを使いました。 AWS Lambdaの関数をnpmでパッケージ管理 - Qiita
このプロジェクトを用いることで、npmからAWS Lambda用のパッケージを作成・デプロイまで行うことが可能です。 上記のパッケージを使う際にハマった点を共有しておきます。
Scriptで定義されているコマンド郡の動かし方がわからない。
npm testだけは動いたのですが、他のbuild等のコマンドがうまく動きませんでした。 以下のようにすることでScript内で定義されているコマンドを動かすことが可能でした。
$npm run build
Roleの指定方法がわからない。
AWS Lambda Functionをアップロードする際に、 設定ファイルとして作成するlambdaConfig.jsonの内のRoleの記述方法わからず悩みました。 こちらはAWS Management Console内のIAM > Roles 内のarn:aws:iam::から始まる文字列を入力する必要があります。
npm run publishがうまくできない
package.jsonで指定しているaws-sdkのバージョンを更新した際に発生しました。 Lambdaのオブジェクトを作成する際に、apiVersionを明記すること必要がありました。
./script/publish.js
var lambda = new aws.Lambda({apiVersion:'2014-11-11', region: lambdaConfig.region}),
zipPath = 'pkg/' + pkgConfig.name + '.zip';
publishしたfunctionのテストに失敗する。
npm run initLambdaで作成したひな形ファイルにはhandlerFile・handlerMethod が作成されていないのが原因です。 上記の作成と、未設定時にapp.jsに定義したhandlerでアップロードするようにしてみました。
./script/initLambda.js
var fs = require('fs');
var config = {
region: '',
description: '',
role: '',
memorySize: '128',
timeout: '3',
handlerFile:'',
handlerMethod:''
};
fs.writeFileSync('./lambdaConfig.json',JSON.stringify(config));
./script/publish.js
function buildHnadlerName(lambdaConfig){
if(!lambdaConfig.handlerFile){
lambdaConfig.handlerFile = 'app';
}
if(!lambdaConfig.handlerMethod){
lambdaConfig.handlerMethod = 'handler'
}
return lambdaConfig.handlerFile + '.' + lambdaConfig.handlerMethod;
}
なお、上記の修正を適用した版を以下のブランチに配置しました。 こちらも併せて見ていただければ幸いです。 CM-Kajiwara/myFirstLambda
Amazon API Gatewayに作ったAWS Lambda Functionをデプロイする。
Deployに関しては、下記のブログを参照していただければと思います。 また、今回の作例ではAPI認証も実施しています。 Amazon API Gateway – API作成から動作確認までやってみる | Developers.IO Amazon API GatewayでAPIキー認証を設定する | Developers.IO
ブラウザからAmazon API Gatewayを呼ぶ
今回の作例では、Amazon API GatewayとWebサーバーとクロスドメインになるため、 ブラウザからCORSの設定を行う必要があります。 Amazon API Gateway をクロスオリジンで呼び出す (CORS) | Developers.IO
CORSの設定まで行えれば、呼び出すのはjQueryからでも、 生成されたSDKからでも呼び出すことが可能です。
<!doctype html>
<button id="callSDKFunction">Sample Click callSDKFunction</button>
<button id="calljQueryAjax">Sample Click calljQueryAjax</button>
<div id="imageContainer"></div>
上記を動かした画像が下記になります。 ボタンを押下することで、Amazon API GatewayよりLambdaから S3のPre-Signed URLを取得し、imgタグに挿入しているといった流れになります。
まとめ
API Gatewayをブラウザから扱ってみました。 CORSの設定が必要ではありますが、 そこさえ押さえてしまえば普通のREST APIとして呼び出すことができました。