前提
Lambdaプロキシ統合を使用(LAMBDA_PROXY, Lambda Proxy)
→APIGatewayの統合リクエストで「Lambda プロキシ統合の使用」をチェック。
テンプレート(とりあえず早く使いたい人用)
'use strict';
//External Libraries
//const hoge = require("hoge");
module.exports.functionname = (event, context, callback) => {
//Respomse Template
var response = {
statusCode: 200,
headers: {"Access-Control-Allow-Origin" : "*"},
body: null
};
//Response.Body Template
var body = {
message: 'successfully!',
input: event,
results: null
};
try {
var results = '';
body.results = results;
response.body = JSON.stringify(body);
callback(null, response);
} catch(e) {
//Exception
response.statusCode = 500;
body.message = e.message;
response.body = JSON.stringify(body);
callback(null, response);
} finally {
}
};
基本的な記述(serverlessより)
例:handler.json
'use strict';
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
headers: {"Access-Control-Allow-Origin" : "*"},
body: JSON.stringify({
message: 'successfully!',
input: event,
}),
};
callback(null, response);
};
レスポンスの注意
Lambdaプロキシ統合を使用している場合、
「statusCode」
「headers」
「body」
は必須になるので注意。
※入れないと、サーバエラーになります
※bodyの値は文字列じゃないとダメ
LambdaでCORSを有効にするには
そもそもCORSってなによって方はこちらへ↓
CORS簡易まとめ
このページでは、前提として「Lambdaプロキシ統合」があるので、
レスポンスのヘッダ情報に
「"Access-Control-Allow-Origin" : "*"」
を加えるだけ。
解説:module.exports.関数名
まず、この記述の仕方は何か。
→この関数が、外部モジュールとして読み込まれたときの使い方を設定している。
深く考えたくなかったら↓
こういうものだと思って関数を定義すれば良い。
よく知りたいなら↓
外部モジュールは
var hoge = require('ファイル名');
で読み込まれる。(Node.jsの場合)
requireの戻り値を設定するために、
呼ばれた関数では「exports」か「module.exports」で定義しなければならない。
違いは、
説明 | |
---|---|
exports | オブジェクトとして返す。 複数のプロパティを内包させたいときに使う。 |
module.exports | オブジェクトをセットした変数?を返す。 クラスや単一のオブジェクトをrequireさせたいときに使う。 |
解説:event
Lambdaが受け取るリクエストパラメータのようなもの。
Lambdaと紐付けるサービスによって、変幻自在。
API Gatewayの場合、
統合リクエストのタイプ「LAMBDA_PROXY」を使うと手早くすすめるので、
それを使いましょう。
※マッピングテンプレートでせかせか作るのはプロにまかせましょう
よく使う情報の参照方法
1. クエリパラメータ
event.queryStringParameters.パラメータ
※注意
クエリパラメータが皆無の場合、「event.queryStringParameters = null」となり、
上記参照方法も例外となる。
状況に応じては、
if(event.queryStringParameters !== null && event.queryStringParameters !== undefined) {
if(event.queryStringParameters.id !== null && event.queryStringParameters.id !== undefined) {
id = event.queryStringParameters.id;
}
}
↑こんなチェックも必要かも。
2. POSTパラメータ
event.body
※注意
POSTパラメータは文字列で必ず渡ってくる。
つまり、
# 通常形式
id=1&name=hoge
# JSON形式
{id:1, name:'hoge'}
もLambda内では一度使いやすいようにパースしてあげる必要がある。
ゆるふわな方法は後述。
(serverless)ローカルでeventに情報を渡す
- 事前にjsonファイルで渡すデータを作っておく。
{
"queryStringParameters": {
"id": 2
}
}
2.invokeするときに、作ったjsonファイルを読み込み
sls invoke local -f 関数名 -p jsonファイル
eventの中身
{
"resource": "/index",
"path": "/index",
"httpMethod": "GET",
"headers": null,
"queryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
"accountId": "xxxxxxxxxxxx",
"resourceId": "xxxxxx",
"stage": "test",
"requestId": "xxxxxxxxxxxxxxxxxxx",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": "xxxxxxxxxxxx",
"cognitoIdentityId": null,
"caller": "xxxxxxxxxxxx",
"apiKey": "xxxxxxxxxxxxxxxxxxx",
"sourceIp": "xxxxxxxxxxxxxxxxxxxxx",
"accessKey": "xxxxxxxxxxxxxxxxxxxx",
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": "arn:aws:iam::xxxxxxxxxxxx:xxxx",
"userAgent": "Apache-HttpClient/4.5.x (Java/1.8.0_102)",
"user": "xxxxxxxxxxxx"
},
"resourcePath": "/index",
"httpMethod": "GET",
"apiId": "xxxxxxxxxx"
},
"body": null,
"isBase64Encoded": false
}
解説:context
ランタイム情報を格納している。
使用メモリ数くらいは使えそう。
解説:callback
LambdaのNode4.3からサポートが追加されたもの。
ファンクションを明示的に終了するために使われる。
正直、どういう挙動をするものなのかまだよく理解できていない。
## 定義
callback(Error err, Object response);
## 関数実行終了
callback();
## 関数の実行に失敗
callback(err);
## 関数の実行に成功
callback(null, response);
引数 | 説明 |
---|---|
Error err | 失敗時にErrorオブジェクトにその内容がセットされる |
Object response | 成功時の返却値 JSONにしないとだめ |
JSON.stringify(value[, replacer[, space]])
指定した値をJSON形式に変換してくれる。
何も考えたくなければ、
JSON.stringify(value, null, 2);
が良いかと思う。(フィルタなし、半角スペース2でインデント整形)
引数 | 説明 |
---|---|
value | JSONに変換したいものを指定 |
replacer | 指定した関数か配列でフィルタをかける 関数→引数key,valueでフィルタ処理をかける 配列→指定値をkeyとして、それをフィルタ(削除) |
space | 結果JSONのインデントを整えてくれる。 数値なら半角スペースで(最大10),文字列ならそれをインデント文字として使う(タブ文字なら\tなど) |
外部ライブラリをいれよう
npm install mysql2 --save-dev
※node_modulesディレクトリに配置される
'use strict';
const mysql = require('mysql2');
module.exports.hello = (event, context, callback) => {
~
mysql2を使ってみよう
設定ファイルを準備
mkdir config && touch config/db.json
cat << EOS >> config/db.json
{
"name": {
"host": "localhost",
"user": "root",
"password": "pass",
"database": "db_name"
}
}
EOS
処理を記載
'use strict';
const db = require("./config/db");
const mysql = require('mysql2');
module.exports.hello = (event, context, callback) => {
var response = {
statusCode: 200,
headers: {"Access-Control-Allow-Origin" : "*"},
body: null
};
var body = {
message: 'successfully!',
input: event,
results: null
};
var con = null;
try {
//[1]コネクション作成
con = mysql.createConnection(db.zpms);
//[2]クエリ実行
con.query('SELECT * FROM tb_test', (err, results, fields) => {
//[3]結果をレスポンスに
body.results = (err === null) ? results : err;
response.body = JSON.stringify(body);
//[4]完了
callback(null, response);
});
} catch(e) {
response.statusCode = 500;
body.message = e.message;
response.body = JSON.stringify(body);
callback(null, response);
} finally {
//[5]ちゃんとコネクションは閉じること
con.end();
}
};
※con.endを明示的にしないと、Lambdaの実行が終わらない(タイムアウトまで)
※プリペアードステートメントで
try {
var first = 1;
var second = 2;
con = mysql.createConnection(db.zpms);
con.query('SELECT * FROM tb_test WHERE id IN (?, ?)', [first , second ], (err, results, fields) => {
body.results = (err === null) ? results : err;
response.body = JSON.stringify(body);
callback(null, response);
});
} catch(e) {
~
POSTパラメータをパースしよう
バリデータとパーサーをインスコ
npm install validator qs --save-dev
処理
const validator = require('validator');
const qs = require('qs');
~
var pParam = null;
if(event.body !== null) {
pParam = (validator.isJSON(event.body)) ? JSON.parse(event.body) qs.parse(event.body);
}