Azure API Managementポリシーを使ったリダイレクト

## はじめに
Webアプリを運用していると、例えば「アプリのバージョンアップで旧アプリから新アプリに移行し、旧アプリを閉塞させたい」といったケースがあるかと思います。

その際、新アプリのリリース後にユーザーが間違えて旧URLでアプリにアクセスしてしまうこともあるかと思いますが、そういった場合は適切に新URLにリダイレクトさせる必要があります。

こういったリダイレクトの処理はAzure API Managementでポリシーの設定を利用することにより解決できます。

リダイレクトの機能のみですと[Azure FrontDoor](https://learn.microsoft.com/ja-jp/azure/frontdoor/front-door-overview)でもサポートされていますが、API Managementの場合は独自のロジックを組み込めるため、より細かいリダイレクトのポリシーを実現することができます。

ユーザーが旧アプリのURLにアクセスした場合であっても新アプリにリダイレクトさせ、旧アプリの実質的な閉塞が可能です。

![概要.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398865/f56c95f4-6fe9-2653-4960-0484cab10d5c.png)

## 前提
* 新アプリ/旧アプリは、それぞれApp Services等に既にデプロイ済みとします。
* API Managementでは、旧アプリ用/新アプリ用2つのAPIがあるとします。
    * 本記事ではそれぞれの設定は下記の通りとします。
        * 旧アプリ
            * Base URL: `https://<API Managementドメイン>`
* API URL suffix：なし

              ![5-999c32ce-5cac-429f-9542-fea899f23996.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398865/51a26ee9-36a6-64f6-2e86-abd33b468237.png)

        * 新アプリ
            * Base URL: `https://<API Managementドメイン>/v2`
            * API URL suffix：v2

              ![6-1367eb4e-2862-42ca-bf73-f0fd71a40e30.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398865/41da1a71-fb77-8987-9cf7-897addfb8390.png)

## API Managementポリシー設定
旧アプリ側のGETオペレーションのInbound processingポリシーに下記の要素を追加します。

Azure PortalのUIではこちらを選択するとポリシーの編集画面になります。

![1-7c83bf48-24fb-4fbf-893b-02b974534af2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398865/c39d2cbf-0d3a-e038-dbbb-87fa7f061d74.png)

```xml
<policies>
    <inbound>
        <base />
        <!-- 追加 -->
        <return-response>
            <set-status code="303" reason="Redirecting" />
            <set-header name="Location" exists-action="override">
                <value>@{
                    return "/v2";
                }</value>
            </set-header>
        </return-response>
        <!-- /追加 -->
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>
```


## 解説
ポリシーの中でも、今回追加した箇所をピックアップします。

```xml
<return-response>
    <!-- 303ステータスコードを返す -->
    <set-status code="303" reason="Redirecting" />
    <!-- ヘッダーのLocationを編集 -->
    <set-header name="Location" exists-action="override">
        <value>@{
            return "/v2";
        }</value>
    </set-header>
</return-response>
```

上記では、`return-response`ポリシーを利用してAPI Managementからのレスポンスをカスタマイズしています。

今回カスタマイズしているのは、下記の2点です。
* `set-status`でのステータスコードの定義
    * `303`でリダイレクトのコードを指定
* `set-header`でのレスポンスヘッダーの上書き
    * `Location`ヘッダーでリダイレクト先のパスを指定

参考：https://learn.microsoft.com/ja-jp/azure/api-management/return-response-policy

## 動作確認
API Managementで変更を適用後、旧アプリへのURLにアクセスしてみましょう。

* URL例：`https://<API Managementサービス名>.azure-api.net/`

アクセス後にURLを確認すると、新URLにリダイレクトできていることが確認できます。

![4-d7ff307d-074f-49fb-bd5f-28028ab13e91.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398865/7a09d721-2d15-2e2e-c34d-8ec2fef5b4aa.png)

さらにブラウザの開発者ツールでネットワークログを確認すると、下記のログが確認できます。（キャプチャはChromeのネットワークログです）

1. リダイレクトのログ
    * URL：`https://<API Managementサービス名>.azure-api.net/`
    * ステータス：303
1. 新URLのログ
    * URL：`https://<API Managementサービス名>.azure-api.net/v2`
    * ステータス：200

 ![3-9671997c-d2e0-4382-8b43-96187b53fcb9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398865/63b1d59f-64c5-a510-237b-5ce684666f43.png)

1.のログの詳細を見ると、レスポンスヘッダーのLocationに新アプリのパスがあることも確認できます。

![2-ebe769ca-bdbe-4fb0-8113-7ab276675910.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398865/c6917996-b2ea-5029-4f72-c386d5d6fd33.png)

## まとめ
今回はAPI Managementポリシーを利用したリダイレクト処理をご紹介しました。

もちろんリダイレクト処理をアプリ側のソースコードで定義することもできますが、API Managementで定義してしまえばアプリのソースコードやフレームワークに依存せずにリダイレクト処理ができ、アプリへのアクセス前に処理が実行されますので比較的リダイレクト処理が速くなります。

また、API Managementポリシーでは独自APIの呼び出しもサポートされています。

**次回は独自APIを組み込み、条件に応じてリダイレクトさせる方法についてご紹介しようと思います。**

## 参考
* [API Management ポリシー リファレンス](https://learn.microsoft.com/ja-jp/azure/api-management/api-management-policies)
    * [応答を返す](https://learn.microsoft.com/ja-jp/azure/api-management/return-response-policy)