ンンンパ

ふとしです

移転しました

AWS Lambdaで使う関数をローカルでテストするサーバーを建てる。

AWS Lambda + AWS Api Gateway + AWS DynamoDBでなにかをつくることにはまっています。

AWS Lambdaで使う関数自体はmochaなどでテストできますが、実際にブラウザから叩くテストをローカルでしたいと思いました。

そこでNode.jsで簡単なサーバーを建てます。

まず、AWS Lambdaはこのような関数です

"use strict";

const Workbook = require('./src/workbook').Workbook;
const Marker = require('./src/marker').Marker;

exports.handler = (data, context, callback) => {
  let workbook = new Workbook(data);
  let marker = new Marker(workbook, data);

  marker.mark((result) => {
    if (result) {
      context.succeed({result: 'correct', data: marker.explain()});
    } else {
      context.fail(JSON.stringify({result: 'incorrect', data: marker.explain()}));
    }
  });
};

WorkbookMarkerがDynamoDBにアクセスします。環境変数を使って、内部で参照ファイルを切りかえ、ローカルのDynamoDBにアクセスするようにしているので、そちらは大丈夫です。

テストサーバーです

サーバー側の言語をまともに触ったのはNode.jsがはじめてで、はじめて書いたのもこのような簡易なサーバーでした。非常に懐かしいですね。

import * as http from 'http';
import * as qs from 'querystring';
import * as marker from '../marker/index';

http.createServer(function (req, res) {
  if (req.method !== 'POST' && req.method !== 'OPTIONS') {
    res.end('');
    return;
  }

  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'POST');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
  res.setHeader('Content-Type', 'application/json');

  if(req.method === 'OPTIONS'){
    res.end(``);
    return;
  }

  let body = '';
  req
    .on('data', (data) => {
      console.log('data', data);
      body += data
    })
    .on('end', () => {
      qs.parse(body);

      marker.handler(JSON.parse(body), {
        succeed: (data)=> {
          res.end(JSON.stringify(data));
        },
        fail: (stringifiedData)=> {
          res.end(stringifiedData);
        }
      });
    });

}).listen(process.env.PORT || 3080, '127.0.0.1');

OPTIONSによるプリフライト対応処理を追加しました。(昨日は素のPOSTだけ飛んでたのにな……)

まずPOSTOPTIONS以外はハネます。

つぎに、データの整形ですね。こういうのは自動でやってくれないんでしょうか。

marker.handlerがAWS Lambdaでの関数本体なので、そこへデータを投げます。

context.succeescontext.failで関数を終了するつくりなので、そこに関数を妖異します。その関数呼び出しをもってJSONレスポンスを作成します。

実際のfailでは{errorMessage: 引数}というレスポンスになりますが、これはAWS Api Gatewayで整形します。ので、それを踏まえたJSONとします。

$ TEST=true babel-node test-server/index.js

テストできた

これでブラウザ側からSuperagentなどを使いPOSTすると、実際のレスポンスが得られるようになりました。

クリッククリックで行うテストがはかどりますね。