このエントリは2024/04/22現在の情報に基づきます。将来の機能追加や変更に伴い、記載内容からの乖離が発生する可能性があります。
問い合わせ
いつもの人から、こんな問い合わせが届いた。
現在Path Parameterを使うようなAPIをBackend Serviceとして利用しようと考えている。API利用者にAPI Gatewayをバイパスされたくないので、パラメータをいろいろ変更しておきたい。そのためにも、Path ParameterをQuery Parameterに置き換える必要があるのだが、Azure API Managementではどのように構成すればよいか?
Backend Serviceの隠蔽のために、パラメータの並びや種類を変更するのはよく行われている。Query Parameter/Path Parameter間の変換はそれこそStackOverflowあたりに情報が転がっているのだが、実際に問い合わせをもらうことが多いのも確かなので、備忘録がてら残しておくことにする。いずれにしても、主として利用するのはrewrite-uri
ポリシー。
前提条件
Base URLと変換のルールは以下の通りとする。ただし、パラメータの値が存在しない場合はnotfound
という文字を入れるものとする(ここは状況に応じてルールが変わるはずだが、今回はサンプル&わかりやすさを考慮してこのルールを採用した)。
API Service (Frontend) | Backend Service | |
---|---|---|
Base URL | <APIM_URL>/api | <BackendService_URL>/api |
Query to Path | /query?q={param} | /path/{param} |
Path to Query | /path/{param} | /query?q={param} |
Query parameterからPath parameterへの変換
前提条件のルールに記載した通り、Frontendの設定は以下のようになっている。Backend Serviceは /path/{param}
を期待している。
この場合、以下のようにポリシーを構成すればよい。
<policies>
<inbound>
<base />
<rewrite-uri id="setPathParam" template="@("/path/"+context.Request.Url.Query.GetValueOrDefault("q", "notfound"))" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
Path parameterからQuery parameterへの変換
前提条件のルールに記載した通り、Frontendの設定は以下のようになっている。Backend Serviceは /query?q={param}
を期待している。
この場合、以下のように3種類の方法が考えられる。[2] が一番簡単。[1]、[3]はコンテキスト変数を使って値の検証も追加できるとともに、ポリシー内でデフォルト値を設定できる。
なお、Path parameterの定義でデフォルト値を設定できるが、呼び出し時に制約をかけるわけではないため、すべての方法で値を指定せずに呼び出せてしまう点は認識しておく必要がある。また、各実装方法で、値指定なし呼び出し時の挙動が異なるので注意が必要。
方法1 | 方法2 | 方法3 | |
---|---|---|---|
OpenAPI Specにて、Path parameterへデフォルト値を設定 | ✅ | ✅ | ✅ |
デフォルト値の設定 | ✅ | ✅ | |
値なしでの呼び出し | デフォルト値をつけてBackend Serviceを呼び出す | Backend Serviceの実装に依存 | デフォルト値をつけてBackend Serviceを呼び出す |
[1] コンテキスト変数とrewrite-uri
ポリシーを使う
<policies>
<inbound>
<base />
<rewrite-uri id="setQueryParam" template="@("/query?q="+context.Request.MatchedParameters.GetValueOrDefault("param","notfound"))" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
[2] rewrite-uri
ポリシーのみ使う
<policies>
<inbound>
<base />
<rewrite-uri id="setQueryParam" template="/query?q={param}" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
[3] set-query-parameter
ポリシーも使う
一番冗長だが、set-query-parameter
ポリシーを使って以下のようにも記載できる。
<policies>
<inbound>
<base />
<rewrite-uri id="setQueryParam" template="/query" />
<set-query-parameter name="q" exists-action="override">
<value>@(context.Request.MatchedParameters.GetValueOrDefault("param","notfound"))</value>
</set-query-parameter>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
おまけ
以下のURLにチートシート的に使えるポリシー式のサンプルがあるので、こちらも案内しておいた。
Common policy expressions
https://github.com/Azure/api-management-policy-snippets/blob/master/policy-expressions/README.md