Azure Functions で REST な API を作る


Azure Functions で REST っぽい WebAPI を作りたいです。

REST な API については、

* [0からREST APIについて調べてみた - Qiita](https://qiita.com/masato44gm/items/dffb8281536ad321fb08)

にある通りで。

例えば、日本の住所を REST な API で考えると、

```
GET https://hoge.com/api/address/23      <-- 愛知県のデータを取得
GET https://hoge.com/api/address/23/106  <-- 愛知県/名古屋市中区のデータを取得

POST https://hoge.com/api/address/23/112 <-- 愛知県/名古屋市南区のデータを追加
PUT  https://hoge.com/api/address/23/113 <-- 愛知県/名古屋市守山区のデータを更新

DELETE https://hoge.com/api/address/13   <-- 東京都のデータを削除
```

という感じになります。あ、説明不足でごめん ``23`` は総務省が定めた [都道府県コード](http://www.soumu.go.jp/denshijiti/code.html) 、``112`` は [市区町村コード](http://www.soumu.go.jp/denshijiti/code.html) (の下3桁)です。

このような API を Azure Functions で作りたいと思っても、通常の Http Trigger では「動的な」「多段の」パスは定義できません。

## Azure Functions のプロキシを使う

そんなときに使えるのが Azure Functions のプロキシ(関数プロキシ)機能です。

* [Azure Functions でのプロキシの操作 | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-proxies)

関数プロキシは Http Trigger な Function の前に配置され、URL やクエリ文字列、リクエストメソッドやレスポンスのカスタマイズを可能にします。ちょうど AWS の API Gateway に相当する機能だと考えられます。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Azure Functions でも、こんな機能を使って束ねることができます。<a href="https://t.co/GrXX7yLo6K">https://t.co/GrXX7yLo6K</a> previewだと思うけど。</p>&mdash; Takekazu Omi (@takekazuomi) <a href="https://twitter.com/takekazuomi/status/1022301008972541952?ref_src=twsrc%5Etfw">2018年7月26日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## プロキシを使ってみよう

実際に REST API っぽい使い勝手を、プロキシを使って実現してみます。

ドンッ！！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/8227/14cee5a9-6f42-4670-13f6-0e84df8f5b08.png)

Functions Apps にプロキシというグループがあるので、そこに新しいプロキシを作ります。名前 "Proxy01" は任意の名称で、これは外部に公開される URL には影響を与えません。

### 変数の利用

ルートテンプレートで、 ``{table}`` や ``{*path}`` と付けているのが変数で、名称は任意です。

``{table}/{*path}`` と定義すると、呼び出した URL のパス要素が、その変数に格納されます。

例えば次のようになります。

```
https://hoge.com/rest/address/23  ---> table='address', path='23'
https://hoge.com/rest/address/23/201  ---> table='address', path='23/201'
```

という感じで変数にURLパスが格納されます。定義で ``*path`` とすると、「そこまでのパス文字列すべて」が格納されます(``23/201`` のように)。

そしてこの変数を別な場所で使用できます。ここでは **要求のオーバーライド** の項目で、クエリパラメータとして利用します。

例えば、 ``table : {table}`` という定義は、ルートテンプレートで定義した {table} 変数をクエリパラメータの ``table`` にマッピングする、という意味です。

``{request.method}`` は組み込みの変数で、URL呼び出しのリクエストメソッド(GET/POST/PUTなど)を示します。

そして、このプロキシの透過先、実際の呼び出し先が **バックエンドURL** で指定されたURLで、通常は別な Http Trigger Function になると思います(このUIだけ見ると、Azure Functionsに限らず任意のURLを指定できるようですが)。

つまり、
``https://hoge.com/rest/address/23/201`` 
という URL が、別な URL
``https://huga.com/MyHttpTrigger?table=address&path=23/201`` 
に変換できたとみなせます。

あとは、バックエンドURLの方でクエリ文字列をよしなに処理すれば、REST っぽい API が実装できそうです。
（``https://hoge.com/api/address/23/112`` のようなリストの中の要素をダイレクトに示すURLは、 path に ``23/112`` が入るだけなので、この文字列を自力でパースする必要はあります。）

Azure Functions の Http Trigger では次のようにクエリ文字列から ``table``, ``method`` , ``path`` を取り出せるので、あとは SQL を組み立てるなり、DAO(Data Access Object) にお任せするなりできます。

**MyHttpTrigger の index.js**

```javascript
module.exports = function (context, req) {
    const table = req.query.table || '';
    const method = req.query.method || '';
    const path = req.query.path || '';

    context.res = {
        headers: {
            'Content-Type': 'application/json'
        },
        body: `table=${table}, method=${method}, path=${path}`
    };
    context.done();
};
```