AWSにServerless Frameworkを利用してRESTfulAPIを作成する際、クエリー文字列などの引数を取得する方法についてメモします。今回はAPI Gatewayのテンプレート関連の機能は使わず、Lambda側ですべて処理します。利用する言語はNode.jsです。
基本的な考え方
クエリーを受け取る
引数eventの中にqueryStringParameters
というプロパティがありますので、これを参照するだけ。例えばURL/dev/hello?foo=bar
のクエリfooを参照したかったら以下のようにするだけです。
module.exports.echo1 = async event => { const foo = event.queryStringParameters.foo; // (略) }
ただこれだけだとfooが渡されなかった場合に実行時エラーとなってしまうため、以下のようにチェックが必要です。
module.exports.echo1 = async event => { const query = event.queryStringParameters; const foo = ((query !== null) && ("foo" in query))? query.foo:"fooが渡されませんでした"; // (略) }
クエリーが1件も渡されなかった場合はevent.queryStringParameters
はnull
になります。
リクエストボディを受け取る
POSTなどで渡されたリクエストボディのデータを受け取りたい場合はevent.body
を参照します。ただし特にパースやデコードが一切されていない生の文字列のまま入っていますので、扱いやすいように下準備をする必要があります。
application/json
以下の例ではJSON形式で渡されたリクエストボディをJavaScriptで扱えるようにパースを行っています。こちらもクエリーと同様にリクエストボディが空の状態で呼び出された場合event.body
はnull
になります。
module.exports.echo1 = async event => { const body = JSON.parse(event.body); const foo = ((body !== null) && ("foo" in body))? body.a:"fooが渡されませんでした"; // (略) }
x-www-form-urlencoded
JSON形式ではなくa=123&b=456
といった形式の文字列を扱う場合には、自前でデコード&パース処理を書いても良いのですが既存のモジュールを使ってあげると手早くできます。
というわけでquery-stringモジュールをインストール。
$ npm install query-string
以下のようにモジュールを読み込みevent.bodyをparseしてあげるだけです。
const queryString = require("query-string"); module.exports.echo2 = async event => { const body = queryString.parse(event.body) // 略 }
実際に試している
準備
今回は「echo」という名前のプロジェクトを作成しました。
$ serverless Serverless: No project detected. Do you want to create a new one? Yes Serverless: What do you want to make? AWS Node.js Serverless: What do you want to call this project? echo
ディレクトリが作成されているはずですので、中に入ってnpm init
しておきます。
$ cd echo $ npm init
このあたりの詳細は過去記事を参照ください。 blog.katsubemakito.net
サンプルコード
serverless.yml
プロジェクトの設定を行います。URL/(stage)/echo
をGETでリクエストするとecho1を、POSTでリクエストするとecho2を実行するよう設定しています。
service: echo provider: name: aws runtime: nodejs12.x functions: echo1: handler: handler.echo1 events: - http: path: echo method: get echo2: handler: handler.echo2 events: - http: path: echo method: post
handler.js
実際のコードです。handler.jsの中に以下の2つの関数をそのまま貼り付けます。
'use strict'; /** * GET /(stage)/echo?foo=xxxxx */ module.exports.echo1 = async event => { const query = event.queryStringParameters; const foo = ((query !== null) && ("foo" in query))? query.foo:"foo is empty"; return { statusCode: 200, body: JSON.stringify( { message: 'Im echo1', query: foo, }, null, 2 ), }; }; /** * POST /(stage)/echo/ * foo=xxxxx */ module.exports.echo2 = async event => { const body = JSON.parse(event.body) const foo = ((body !== null) && ("foo" in body))? body.foo:"foo is empty"; return { statusCode: 200, body: JSON.stringify( { message: 'Im echo2', body: foo, }, null, 2 ), }; };
デプロイ
deployコマンドでAWSへ反映します。
$ serverless deploy
途中でURLが表示されるのでこれをメモします。
endpoints: GET - https://38unnrqr5b.execute-api.us-east-1.amazonaws.com/dev/echo POST - https://38unnrqr5b.execute-api.us-east-1.amazonaws.com/dev/echo
実行する
ではcurlコマンドで挙動を確認します。まずはGETでクエリー文字列を取得します。
$ curl 'https://38unnrqr5b.execute-api.us-east-1.amazonaws.com/dev/echo?foo=12345' { "message": "Im echo1", "query": "12345" }
次にPOSTでリクエストボディの値を取得します。
$ curl -X POST \ -H "Content-Type: application/json" \ -d '{"foo":67890}' \ 'https://38unnrqr5b.execute-api.us-east-1.amazonaws.com/dev/echo' { "message": "Im echo2", "body": 67890 }