AWS Lambda + API Gateway で、 Movable Type の記事データを取得するエンドポイントを設定する

Movable Type には 「Data API」 というREST APIがあり、記事データなどAPI経由で取得することができます。

Data APIを利用するためには、APIのエンドポイントへ通信を行う必要があります。このとき、JavaScript などでコードを書くと、Data APIのURIを記述することになるため、Movable Type がインストールされている場所がある程度特定できます。

一方で、セキュリティの観点から、Movable Type の場所を隠したい、という要求もあるでしょう。

そこで、AWS Lamdba + API Gateway を利用して、

「Movable Type のData APIの場所を隠しつつ、AWSのAPI Gateway 経由で、記事データを取得する」

をやってみました。

## やること

* AWS Lambda で、Movable Type の Data API から記事データを取得する
* API Gateway から、上記のデータを取得できるようにエンドポイントを公開する

## 流れ

* Lambda でMovable Type の API からデータを取得する関数を作成する
* API Gateway でエンドポイントを設定する
* Lambda 関数とAPI Gateway を紐付ける


## Lambda で Movable Type の APIからデータを取得する関数を作成する

最初に、Lambda 関数用のコードを記述します。
今回は、Node.jsの「request」パッケージを利用して通信を行います。

任意のパッケージ作成用ディレクトリを作成。ここでは「work」とする。

```
mkdir work
```

作業用ディレクトリに移り、Node.jsを利用するためにnpm init して、requestパッケージをインストール

```
cd work
npm init
npm install request
```
Movable Type から記事データを取得するコード、index.jsを作成。

```javascript
exports.handler = function(event, context, callback) {

  'use strict';

  // requestを読み込み
  // Movable Type の Data APIエンドポイントを変数に定義
  
  const request = require('request');
  const URL = 'http://your-mt/mt-data-api.cgi/v3/sites/サイトID/entries';

  // 関数「getEntries」で取得した記事データをコールバックで返す

  getEntries().then(function(response) {
       callback(null, response);  
    });
  
  // Movable Type のData APIを叩くための関数「getEntries」を作成
  // Promise で取得したJSONデータを返す
  
    function getEntries() {
      return new Promise((resolve, reject) => {
        request.get({
          uri: URL,
          json: true
        }, function(err, req, data) {
          resolve(data);
        });
      });
    }
}

```

上記で作成したファイル一式を、Lambdaにインポートするために、zipで圧縮する。

```
zip -r myLambda.zip index.js node_modules
```

zipファイルが完成したら、Lamdba 関数を作成します。

AWSのコンソールからLambda を選び、新規関数を作成。IAMロールは、Lambdaの実行権限を持つロールを選択。

![mt_lambda_01.png](https://qiita-image-store.s3.amazonaws.com/0/83767/c0e181e0-1b70-e1c8-1051-72db4112cd93.png)


関数を作成したら、前もって作っていたzipファイルをアップロード

![mt_lambda_02.png](https://qiita-image-store.s3.amazonaws.com/0/83767/62a3d5b4-c71c-42fd-773e-35dbfc50b78e.png)


APIへの通信のための時間を見込み、タイムアウト設定を30秒に設定

![mt_lambda_03.png](https://qiita-image-store.s3.amazonaws.com/0/83767/4a5e7e95-3fd2-b80d-94f1-132f961140de.png)

設定が終わったら保存します。

テストケースを作成して、実行。Movable Type から記事データが取得できていれば成功です。

次に、Lambda 関数を実行するためにAPI Gateway をトリガーとして設定します。右の一覧からAPI Gateway をトリガーとして選択。

![mt_lambda_05.png](https://qiita-image-store.s3.amazonaws.com/0/83767/51c3cc0e-473a-ab41-b09f-49fa3e2c4440.png)


「新規API」を選択。名前を決めます。なんでも良いですが、今回は「mt」としました。
ステージ名は、公開されるエンドポイントのパス名に含まれる。「mt」としました。
セキュリティは、どこからでも利用できるように「オープン」を選択。

## API Gateway でエンドポイントを設定する

作成したAPI Gateway の設定に移動します。
AWSのコンソール画面から、API Gateway を選択して、作成したAPIの設定画面に移動。

アクションから「リソースの作成」を選択。
このリソース名は、エンドポイントのURLのパスとして使われます。
今回は「entries」としました。

次にメソッドを作成。ここでは「get」を選択。

統合タイプ=>Lambda関数
Lambdaリージョン=>今回作成したLambdaのリージョンを選択
Lambda関数=>今回作成したLambda関数を選択

設定が終わったら保存。

![mt_lambda_09.png](https://qiita-image-store.s3.amazonaws.com/0/83767/81a2ed9d-a31a-6cb8-a07d-a7d07b1f2a1e.png)


保存したら、テストを実行して、期待通りの記事データが取得できているかを確認する。

問題がないことを確認できたら、APIを公開します。
アクションから「APIのデプロイ」を選ぶ。
デプロイするステージは「mt」を選択。

![mt_lambda_11.png](https://qiita-image-store.s3.amazonaws.com/0/83767/3350a36a-7248-2f62-a8cc-e87f286893c4.png)


デプロイが完了したら、左メニューから「ステージ」を選択。今作成したAPIのエンドポイント「https://hogehoge.amazonaws.com/mt/entries」が公開されていることがわかる。

![mt_lambda_12.png](https://qiita-image-store.s3.amazonaws.com/0/83767/310e671c-d275-6d8d-a502-64d4a35291f1.png)

このエンドポイントにGETメソッドでアクセスすると、MTの記事データが取得できます。

![mt_lambda_13.png](https://qiita-image-store.s3.amazonaws.com/0/83767/76136a47-491a-423f-2fbf-ae44912fcc5c.png)


## 積み残しと備考

積み残し：
Lambdaプロキシの統合を試してみる。

備考：
Lambda 関数とAPI Gateway を利用することで、Movable Type のインストール場所を隠すことができる一方で、AWSを経由する分だけ処理時間は長くなる。

どちらを優先するかは考えどころ、と言えそうです。


## 参考情報

http://starhoshi.hatenablog.com/entry/2017/01/07/APIGateway_%2B_Lambda_%2B_NodeJS_%E3%81%A7_rest_api_%E3%82%92%E4%BD%9C%E3%82%8B

https://qiita.com/vankobe/items/ab5bc6487c7e07cb3aba

https://forums.developer.amazon.com/questions/106589/lambda%E3%81%A6request%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95.html