Azure Functions で 作った関数を API として公開し、Movable Type のData API と連携する

[AWS Lambda について書いた記事](https://qiita.com/TakeshiNickOsanai/items/c572f585bd134d31e4f6) の続きです。


Movable Type の REST API機能「Data API」では、記事データなどをAPI経由で取得することができます。

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

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

今回は、Azure Functions  を利用して、

「Movable Type のData APIの場所を隠しつつ、Azure Functions 経由で公開したAPIから記事データを取得する」

をやってみました。

## やること

* Azure Functions で、Movable Type の Data API から記事データを取得し、利用できるようにAzure 上でエンドポイントを公開する
* GETパラメーターを取得できるようにする

## 流れ

* Azure Functions でMovable Type の API からデータを取得する関数を作成
* APIのエンドポイントを設定、公開
* GETパラメーターを解釈できるようにコードを修正


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


### 関数の新規作成

最初に、Azure Portal から実行用の関数を作成します。
手順は [この記事](https://qiita.com/TakeshiNickOsanai/items/46888a059fa8bae9eae0#azure-functions-%E3%81%AE%E8%A8%AD%E5%AE%9A) とほぼ同様です。


* Azure のポータル画面から、[新規]を選ぶ
* 「functions」で検索=>[Functions App]を選択=>[作成]を行う
* アプリ名、リソースグループなどを設定してサービスを立ち上げる

最初のセットアップが終わったら、Functions のカスタム関数から新規関数を登録します。「HTTP Trigger」「JavaScript(=Node.js)」を選択する。

![mt_functions_01.png](https://qiita-image-store.s3.amazonaws.com/0/83767/26d48c24-1348-2bca-2f2c-9c14f43b62e5.png)



関数の作成が終わったら、REST APIとの通信のためのパッケージ「requests」をインストール。
インストールの手順は [この記事](https://qiita.com/TakeshiNickOsanai/items/46888a059fa8bae9eae0#npm%E3%81%AB%E3%82%88%E3%82%8B%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB) の通り。


Movable Type の Data APIから、記事一覧を取得する関数をNode.jsで記述します。
AWS Lambda で作成した関数とほとんど同じですが、

AWS Lambda にNode.jsを実行させるための書式

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

  // Do Something
  callback(null, response); 

}
```

Azure Functions でNjode.js を実行させるための書式

```javascript
module.exports = function (context, req) {

  // Do something

  context.res = {
    // Return Value
  };
  context.done();
}
```

と、微妙に書式が違うため、Functionsの書式に沿って書き換えます。


```javascript
module.exports = function (context, req) {

  'use strict';

  // モジュールと通信のためのエンドポイントを変数に定義
  
  const request = require('request');
  const URL = 'http://path-to-your-mt/mt-data-api.cgi/v3/sites/サイトID/entries';
  
  getEntries().then(function(response) {
  
        context.res = {
          
          headers : {
              "Content-type" : "application/json",
          },
          body: response,
       };
        context.done();
  });
  
  　 function getEntries() {
      return new Promise((resolve, reject) => {
        request.get({
          uri: URL,
          json: true
        }, function(err, req, data) {
          resolve(data);
        });
      });
    }
};
```

記述が終わったら、コードを保存。


![mt_functions_03.png](https://qiita-image-store.s3.amazonaws.com/0/83767/30826645-7f1b-2988-b271-640b2e07c08c.png)


### テスト

テストを実行して、意図通りにMovable Type の記事データが取得できているかどうかを確認する。 うまくいかない場合。「Application Inight」を有効にしてログを確認するなどして状況を確認する。


## APIのエンドポイントを設定、公開

関数の設定が終わったら、APIの公開設定を行います。
関数の左メニューから「統合」をクリック。

APIの各種設定を行う。初期状態では、すべてのメソッドが許可されている。
今回はGETメソッドのみ有効化するため、「Allowed HTTP methods」から「Slected Methods」を選び、GETのみチェックする。必要に応じてメソッドを追加する。

「Authorization level 」は、Fucntions の実行権限範囲を定義する。「Anoymoous」にすると、エンドポイントのURLを知っている人はだれでもアクセス可能なAPIとなる。

トリガー「HTTP」には(req)という文字がある。これは、GETメソッドで渡ってくる値が「req」に格納されているということ。GETメソッドのパラメーターを取得して何かしたい場合、reqを利用する。

![mt_functions_04.png](https://qiita-image-store.s3.amazonaws.com/0/83767/c517efea-8fad-d85c-a611-9239d791781a.png)



設定ができたら保存。

エディタ画面に戻り「関数の URL の取得」をクリックすると、公開されているAPIのURLが確認できる。

APIのURLへアクセスすると、Movable Type の記事データが取得できていることがわかります。

![mt_functions_05.png](https://qiita-image-store.s3.amazonaws.com/0/83767/593a94da-a6c6-cb79-e719-5220bc8daffb.png)


## GETパラメーターを解釈できるようにコードを修正

GETパラメーターで取得できる値をMovable Type に渡せるように変更してみます。

今回は、取得したい記事件数を設定するためのパラメータ「limit」の件数に応じて、Movbale Type の記事取得数を変更できるように修正してみました。

GETのパラメーター「req」にlimitの値が存在する場合、limitの件数をMovable Type の Data APIに渡してあげます。


```javascript
module.exports = function (context, req) {

 'use strict';

 // モジュールと通信のためのエンドポイントを変数に定義
  const request = require('request');
 let URL = 'PATH-TO-YOU-MR/mt-data-api.cgi/v3/sites/サイトid/entries';

  if (req.query.limit) {
 
       URL += '?limit=' + req.query.limit;
   }


 getEntries().then(function(response) {
        context.res = {
        
         headers : {
             "Content-type" : "application/json",
         },
         body: response,
      };
       context.done();
 });
 
    function getEntries() {
     return new Promise((resolve, reject) => {
       request.get({
         uri: URL,
         json: true
       }, function(err, req, data) {
         resolve(data);
       });
     });
   }
};
```


## 参考情報

* https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-create-serverless-api
* https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-http-webhook#webhook---javascript-example
* https://qiita.com/ovrmrw/items/f190e4a8b7fff7c95133