Azure API Management - エラーレスポンスのカスタマイズ

# 目的

エラーレスポンスのヘッダ、ボディをカスタマイズする

# API Managementで検出可能なエラー

[組み込みの手順向けの定義済みエラー](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-error-handling-policies#predefined-errors-for-built-in-steps) と [ポリシーの定義済みのエラー](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-error-handling-policies#predefined-errors-for-policies) があり、それぞれリンク先を参照

ポリシーの定義済みのエラーを検出するためには対応するポリシー（上記リンク先の**source**）を定義しておく必要がある

エラーが発生すると、コントロールが `on-error` ポリシー セクションにジャンプし、エラー情報は `context.LastError` プロパティ内に格納される
`context.LastError` プロパティは [lastError](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-error-handling-policies#lasterror) 参照

# レスポンスヘッダ、ボディのカスタマイズ



## 組み込みの手順向けの定義済みエラー

以下、`404Not Found` のヘッダ、ボディをカスタマイズした例

```xml
<policies>
    <inbound>
        <base />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <choose>
            <when condition="@(context.LastError.Reason == "OperationNotFound")">
                <return-response>
                    <set-status code="404" />
                    <set-header name="Content-Type" exists-action="override">
                        <value>application/json</value>
                    </set-header>
                    <set-body>@{
                        return new JObject(
                            new JProperty("type", "error-type-1"),
                            new JProperty("reason", context.LastError.Reason.ToString()),
                            new JProperty("message", context.LastError.Message.ToString())
                        ).ToString();
                    }</set-body>
                </return-response>
            </when>
        </choose>
        <base />
    </on-error>
</policies>
```

[組み込みの手順向けの定義済みエラー](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-error-handling-policies#predefined-errors-for-built-in-steps)の**Reason**を条件にし、
`set-header`でヘッダ情報の上書き、`set-body`でボディの設定を行っている

`set-header`の詳細は [HTTP ヘッダーの設定](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-transformation-policies#set-http-header) 参照

`set-body`の詳細は [本文の設定](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-transformation-policies#set-body) 参照

上記は`context.LastError` プロパティにアクセスするために `set-body` に [API Management ポリシー式](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-policy-expressions#context-variable) を使用しているが、固定値のみで構成する場合は以下のように定義できる

```xml
<set-body>Hello world!</set-body>
```

```xml
<set-body>{
    "statusCode": 404,
    "message": "Not Found"
}</set-body>
```



以下、カスタマイズしたレスポンス結果

![image-20211002112953718.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/baab49bb-b9f2-cae0-d435-5e4d73e936c3.png)
![image-20211002112849675.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/fe610795-357f-df6b-6cf6-6ada6c0cb546.png)


## ポリシーの定義済みのエラー

以下、`504 Gateway Timeout` のヘッダ、ボディをカスタマイズした例

```xml
<policies>
    <inbound>
        <base />
    </inbound>
    <backend>
        <forward-request timeout="10" fail-on-error-status-code="true" />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <choose>
            <when condition="@(context.LastError.Reason == "Timeout")">
                <return-response>
                    <set-status code="504" />
                    <set-header name="Content-Type" exists-action="override">
                        <value>application/json</value>
                    </set-header>
                    <set-body>@{
                        return new JObject(
                            new JProperty("type", "error-type-2"),
                            new JProperty("reason", context.LastError.Reason.ToString()),
                            new JProperty("message", context.LastError.Message.ToString())
                        ).ToString();
                    }</set-body>
                </return-response>
            </when>
        </choose>
        <base />
    </on-error>
</policies>
```

[ポリシーの定義済みのエラー](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-error-handling-policies#predefined-errors-for-policies) の**source**にあるポリシーを定義する必要がある
今回の場合は `forward-request` でタイムアウト時間10秒、`fail-on-error-status-code`で `on-error` セクションへのジャンプを有効にしている
その他詳細については [forward-request](https://docs.microsoft.com/ja-jp/azure/api-management/api-management-advanced-policies#elements) 参照

以下、カスタマイズしたレスポンス結果

![image-20211002122917579.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/90decd16-96bb-83fe-0b6e-0e606805eb6a.png)