Azure API ManagementでQuery ParameterとPath Parameterを入れ替える

このエントリは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

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください