1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Azure API ManagementポリシーでREST APIを呼び出す

Last updated at Posted at 2024-01-26

はじめに

Azure API Managementのポリシー内では、独自のAPIを呼び出すことが可能です。

そのため、API Managementのポリシーだけではまかなえない、様々なカスタム処理をアプリへのアクセス前にさせることができます。

今回は、前回の記事で作成したポリシーを拡張し、「携帯端末でPC向けアプリにアクセスした際にモバイル向けアプリにリダイレクトさせる」といった例で、
API Managementで独自APIを呼び出し、その結果に応じてリダイレクトさせる方法ご紹介します。

今回ご紹介する例を図にするとこのようになります。

スライド2.PNG

前提

  • 前回の記事同様、下記を前提としています。
    • PC向けアプリ/モバイル向けアプリは、それぞれApp Services等に既にデプロイ済みとします。
    • API Managementでは、PC向けアプリ/モバイル用2つのAPIがあるとします。
      • 本記事ではそれぞれの設定は下記の通りとします。
        • PC向けアプリ

          • Base URL: https://<API Managementドメイン>

          • API URL suffix:なし

            settings1.png

        • モバイル向けアプリ

          • Base URL: https://<API Managementドメイン>/v2

          • API URL suffix:v2

            settings2.png

独自APIの内容

API Managementで独自APIを呼び出し方の前に、まずは呼び出し先となる独自APIのリクエスト/レスポンスとサンプルコードをご紹介します。

リクエスト例

Request Bodyの内容は下記の通りです。API Managementにアクセスした端末のUserAgentを受け取ります。

{
    "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1"
}

レスポンス例

レスポンスでは、受け取ったUserAgentをもとにリダイレクトをするかどうかの結果を返します。

{
    "isRedirect": true
}

サンプルコード

前述のリクエスト内容で受け取ったUserAgentから、モバイル端末(iPhone, Android)かどうかを判定し、モバイルの場合はリダイレクトするよう結果を返します。

下記はAzure FunctionのHTTP Triggerを利用した場合のサンプルコードです。

Azure Functionのランタイムバージョンはv4、フレームワークは.NET6としています。

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.IO;
using System.Threading.Tasks;

namespace ApiManagementFunction
{
    public static class ApiManagementFunction
    {
        /// <summary>
        /// UserAgentからリダイレクトさせるかを判定する
        /// </summary>
        /// <param name="req"></param>
        /// <param name="log"></param>
        /// <returns></returns>
        [FunctionName("IsRedirect")]
        public static async Task<ActionResult<IsRedirectResponseViewModel>> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);

            var userAgent = ((string)(data?.userAgent)).ToLower();

            var vm = new IsRedirectResponseViewModel
            {
                IsRedirect = false
            };

            // UserAgentからモバイル端末かどうかを判定する
            if (userAgent.IndexOf("iphone") > -1 || (userAgent.IndexOf("android") > -1 && userAgent.IndexOf("mobile") > -1))
            {
                // モバイル端末であれば、リダイレクトさせる
                vm.IsRedirect = true;
            }

            log.LogInformation($"User Agent = {userAgent}, IsRedirect = {vm.IsRedirect}");

            return new OkObjectResult(vm);
        }
    }

    /// <summary>
    /// APIレスポンス用ViewModel
    /// </summary>
    public class IsRedirectResponseViewModel
    {
        /// <summary>
        /// リダイレクトするかどうか
        /// </summary>
        public bool IsRedirect { get; set; }
    }
}

API Managementポリシー設定

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

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

1.PNG

<policies>
    <inbound>
        <base />
        <!-- 追加 -->
        <!-- 1. 独自APIの呼び出し  -->
        <send-request mode="new" response-variable-name="response">
            <!-- API URL -->
            <set-url>https://{your app}.azurewebsites.net/api/IsRedirect</set-url>
            <set-method>POST</set-method>
            <!-- API Request Header -->
            <set-header name="Content-Type" exists-action="override">
                <value>application/json</value>
            </set-header>
            <set-header name="x-functions-key" exists-action="override">
                <value>{your function key}</value>
            </set-header>
            <!-- API Request Body -->
            <set-body>@{
                string userAgent = context.Request.Headers.GetValueOrDefault("User-Agent","");
                return new JObject(
                    new JProperty("userAgent", userAgent)
                ).ToString();
            }</set-body>
        </send-request>
        <!-- 2. APIのレスポンスをオブジェクト型の変数に定義 -->
        <set-variable name="apiResult" value="@(((IResponse)context.Variables["response"]).Body.As<JObject>())" />
        <!-- 3. APIの結果から判定 -->
        <choose>
            <when condition="@((bool)((JObject)context.Variables["apiResult"]).Property("isRedirect"))">
                <!-- 4. リダイレクト -->
                <return-response>
                    <set-status code="303" reason="Redirecting" />
                    <set-header name="Location" exists-action="override">
                        <value>@{
                            return "/v2";
                        }</value>
                    </set-header>
                </return-response>
            </when>
            <otherwise />
        </choose>
        <!-- /追加 -->
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

解説

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

少しコードが複雑になっているので、それぞれ何をしているかの概要のみ説明します。詳細については各項目の参考ドキュメントをご参照ください。

<!-- 1. 独自APIの呼び出し  -->
<send-request mode="new" response-variable-name="response">
    <!-- API URL -->
    <set-url>https://{your app}.azurewebsites.net/api/IsRedirect</set-url>
    <set-method>POST</set-method>
    <set-header name="Content-Type" exists-action="override">
        <value>application/json</value>
    </set-header>
    <set-header name="x-functions-key" exists-action="override">
        <value>{your function key}</value>
    </set-header>
    <!-- API Request Body -->
    <set-body>@{
        string userAgent = context.Request.Headers.GetValueOrDefault("User-Agent","");
        return new JObject(
            new JProperty("userAgent", userAgent)
        ).ToString();
    }</set-body>
</send-request>
<!-- 2. APIのレスポンスをオブジェクト型の変数に定義 -->
<set-variable name="apiResult" value="@(((IResponse)context.Variables["response"]).Body.As<JObject>())" />
<!-- 3. APIの結果から判定 -->
<choose>
    <when condition="@((bool)((JObject)context.Variables["apiResult"]).Property("isRedirect"))">
        <!-- 4. リダイレクト -->
        <return-response>
            <set-status code="303" reason="Redirecting" />
            <set-header name="Location" exists-action="override">
                <value>@{
                    return "/v2";
                }</value>
            </set-header>
        </return-response>
    </when>
    <otherwise />
</choose>

1. 独自APIの呼び出し

ポリシーのsend-requestの部分では、独自APIの定義を行います。

<!-- 1. 独自APIの呼び出し  -->
<send-request mode="new" response-variable-name="response">
    <!-- API URL -->
    <set-url>https://{your app}.azurewebsites.net/api/IsRedirect</set-url>
    <set-method>POST</set-method>
    <set-header name="Content-Type" exists-action="override">
        <value>application/json</value>
    </set-header>
    <!-- API Key -->
    <set-header name="x-functions-key" exists-action="override">
        <value>{your function key}</value>
    </set-header>
    <!-- API Request Body -->
    <set-body>@{
        string userAgent = context.Request.Headers.GetValueOrDefault("User-Agent","");
        return new JObject(
            new JProperty("userAgent", userAgent)
        ).ToString();
    }</set-body>
</send-request>

主な定義内容は下記の通りです。

  • set-url:独自APIのURL
  • set-method:独自APIを呼び出すHTTPメソッド(GET, POSTなど)
  • set-header:独自APIのリクエストヘッダー
    • 上記の例では、Content-Typeおよびx-functions-key(Azure Functionsのキー)を設定しています
  • set-body:Request Body
    • 上記の例では、リクエストに含まれるUserAgentの情報をBodyに設定しています

参考:https://learn.microsoft.com/ja-jp/azure/api-management/send-request-policy

2. APIのレスポンスをオブジェクト型の変数に定義

ポリシーのset-variableの部分では、変数を定義します。

<!-- 2. APIのレスポンスをオブジェクト型の変数に定義 -->
<set-variable name="apiResult" value="@(((IResponse)context.Variables["response"]).Body.As<JObject>())" />

カッコが多く少しわかりづらいですが、上記の例では受け取ったレスポンスをオブジェクト型のapiResultという名前の変数に代入しています。

参考:https://learn.microsoft.com/ja-jp/azure/api-management/set-variable-policy

3. APIの結果から判定

ポリシーのchooseの部分では、ある条件に一致した場合のみ処理を行うよう制御します。C#やJavaのif-else文のようなものです。

<!-- 3. APIの結果から判定 -->
<choose>
    <when condition="@((bool)((JObject)context.Variables["apiResult"]).Property("isRedirect"))">
        <!-- 条件に一致した場合の処理 -->
    </when>
    <otherwise>
        <!-- 条件に一致しなかった場合の処理 -->
    </otherwise>
</choose>

主な定義内容は下記の通りです。

  • whenconditionに条件式を記載し、whenタグ内部ではその条件に一致した場合の処理を実行します。
    • 上記の例では、APIから受け取ったレスポンスのisRedirectがtrueの場合はwhen内部を実行しています。
  • otherwisewhenで定義した条件に一致しなかった場合の処理を実行します。

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

4. リダイレクト

return-responseでは、API Managementからのレスポンスを定義します。

<!-- 4. リダイレクト -->
<return-response>
    <set-status code="303" reason="Redirecting" />
    <set-header name="Location" exists-action="override">
        <value>@{
            return "/v2";
        }</value>
    </set-header>
</return-response>

今回は、モバイル向けアプリのパスへのリダイレクト処理を行っています。

こちらについては、前回の記事をご参照ください。

動作確認

API Managementで変更を適用後、PC向けアプリへのURLにアクセスしてみましょう。

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

まずPCでアクセスしてみると、URLはそのまま変更されずにPC向けアプリにアクセスしています。

1.PNG

次にモバイル端末でアクセスしてみると、モバイル向けURLにリダイレクトできていることが確認できます。(キャプチャはChrome開発者ツールのモバイルエミュレーター機能を利用したものになります。)

ブラウザの開発者ツールでネットワークログを確認すると、下記のログが確認できます。

前回の記事同様に、リダイレクトされていますね。

2.PNG

まとめ

今回はPCアプリ⇒モバイルアプリのAPIでのみリダイレクト対応しましたが、独自APIを改修することで、逆のパターンものリダイレクト処理もできます。

また今回は割愛しましたが、独自APIでDB等の他リソースと連携させることにより様々なカスタマイズもできます。

関連記事

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?