次の方法で共有


Azure Functions の Azure Web PubSub 入力バインド

拡張機能では、さまざまなニーズに対応する 2 つの入力バインドを提供しています。

  • WebPubSubConnection

    クライアントを Azure Web PubSub サービスに接続させるには、それがサービス エンドポイント URL と有効なアクセス トークンを認識している必要があります。 WebPubSubConnection 入力バインディングによって必要な情報が生成されるため、クライアントはこのトークン生成自体を処理する必要がありません。 トークンは時間制限付きで、接続に対して特定のユーザーを認証できます。 そのため、トークンをキャッシュしたり、クライアント間で共有したりしないでください。 この入力バインドと連携する HTTP トリガーは、クライアントが接続情報を取得するために使用できます。

  • WebPubSubContext

    Static Web Apps を使用している場合は、HttpTrigger がサポートされている唯一のトリガーであり、Web PubSub のシナリオでは、WebPubSubContext 入力バインディングを提供し、ユーザーが Web PubSub プロトコルでサービス側からアップストリームの http 要求を逆シリアル化するのに役立ちます。 顧客は、関数で簡単に処理するために、WebPubSubTrigger と比較して同様の結果を得ることができます。 HttpTrigger と共に使用する場合、顧客は、HttpTrigger で公開されている URL をイベント ハンドラーで適宜構成する必要があります。

WebPubSubConnection

次の例は、入力バインディングを使用して Web PubSub 接続情報を取得し、HTTP 経由で返す HTTP トリガー関数を示しています。 次の例では、 UserId は、 ?userid={User-A}などのクライアント要求クエリ 部分を介して渡されます。

[Function("WebPubSubConnectionInputBinding")]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
[WebPubSubConnectionInput(Hub = "<hub>", , UserId = "{query.userid}", Connection = "<web_pubsub_connection_name>")] WebPubSubConnection connectionInfo)
{
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.WriteAsJsonAsync(connectionInfo);
    return response;
}
const { app, input } = require('@azure/functions');

const connection = input.generic({
    type: 'webPubSubConnection',
    name: 'connection',
    userId: '{query.userId}',
    hub: '<hub>'
});

app.http('negotiate', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    extraInputs: [connection],
    handler: async (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get('connection')) };
    },
});

negotiateフォルダーを作成しnegotiate/function.json更新し、次の JSON コードをコピーします。

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "webPubSubConnection",
      "name": "connection",
      "userId": "{query.userid}",
      "hub": "<hub>",
      "direction": "in"
    }
  ]
}

negotiate/init.py で関数を定義します。

import logging

import azure.functions as func

def main(req: func.HttpRequest, connection) -> func.HttpResponse:
    return func.HttpResponse(connection)

この言語の完全なサンプルは保留中です

Java 用 Web PubSub 拡張機能はまだサポートされていません。

認証されたユーザー ID を取得する

認証済みクライアントによって関数がトリガーされている場合は、ユーザー ID 要求を生成済みトークンに追加できます。 App Service 認証を使用すると、認証を関数アプリに簡単に追加することができます。

App Service 認証によって、x-ms-client-principal-id および x-ms-client-principal-name という名前の HTTP ヘッダーが設定されます。この 2 つの HTTP ヘッダーには、認証済みユーザーのクライアント プリンシパルの ID と名前がそれぞれ含まれています。

バインド式 (UserId または {headers.x-ms-client-principal-id}) を使用して、バインディングの {headers.x-ms-client-principal-name} プロパティをヘッダーから値に設定できます。

[Function("WebPubSubConnectionInputBinding")]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
[WebPubSubConnectionInput(Hub = "<hub>", , UserId = "{headers.x-ms-client-principal-id}", Connection = "<web_pubsub_connection_name>")] WebPubSubConnection connectionInfo)
{
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.WriteAsJsonAsync(connectionInfo);
    return response;
}
const { app, input } = require('@azure/functions');

const connection = input.generic({
    type: 'webPubSubConnection',
    name: 'connection',
    userId: '{headers.x-ms-client-principal-id}',
    hub: '<hub>'
});

app.http('negotiate', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    extraInputs: [connection],
    handler: async (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get('connection')) };
    },
});

negotiateフォルダーを作成しnegotiate/function.json更新し、次の JSON コードをコピーします。

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "webPubSubConnection",
      "name": "connection",
      "userId": "{headers.x-ms-client-principal-id}",
      "hub": "<hub>",
      "direction": "in"
    }
  ]
}

negotiate/init.py で関数を定義します。

import logging

import azure.functions as func

def main(req: func.HttpRequest, connection) -> func.HttpResponse:
    return func.HttpResponse(connection)

この言語の完全なサンプルは保留中です

Java 用 Web PubSub 拡張機能はまだサポートされていません。

構成

次の表は、function.json ファイルと WebPubSubConnection 属性で設定したバインド構成のプロパティを説明しています。

function.json のプロパティ 属性のプロパティ 説明
タイプ 該当なし webPubSubConnection に設定されている必要があります。
方向 該当なし in に設定されている必要があります。
名前 該当なし 入力接続バインド オブジェクトの関数コードで使用される変数名。
ハブ ハブ 必須 - この値は、トリガーされる関数の Web PubSub ハブの名前に設定する必要があります。 高い優先順位として属性への値の設定をサポートしていますが、またはグローバル値としてアプリ設定に設定することもできます。
userId UserId 省略可能 - アクセス キー トークンに設定するユーザー識別子要求の値。
clientProtocol ClientProtocol 省略可能 - クライアント プロトコルの種類。 有効な値として、default および mqtt があります。
MQTT クライアントの場合は、 mqttに設定する必要があります。
他のクライアントの場合は、プロパティを省略するか、 defaultに設定できます。
接続 つながり 必須 - Web PubSub Service 接続文字列を含むアプリ設定の名前 (既定値は "WebPubSubConnectionString")。

使用方法

WebPubSubConnection には、次のプロパティが用意されています。

バインディング名 バインドの種類 説明
BaseUri うり Web PubSub クライアント接続 URI。
うり うり Web PubSub 接続の絶対 URI。要求に基づいて生成された AccessToken が含まれます。
AccessToken ひも 要求の UserId とサービス情報に基づいて生成された AccessToken

WebPubSubConnection には、次のプロパティが用意されています。

バインディング名 説明
baseUrl Web PubSub クライアント接続 URI。
URL Web PubSub 接続の絶対 URI。要求に基づいて生成された AccessToken が含まれます。
accessToken 要求の UserId とサービス情報に基づいて生成された AccessToken

Java 用 Web PubSub 拡張機能はまだサポートされていません。

生成されたトークンのその他のカスタマイズ

バインド パラメーターの型に限定すると、リストや配列を渡す方法はサポートされません。 WebPubSubConnection は、サーバー SDK が持つすべてのパラメーター (特に roles) で完全にサポートされているわけではありません。また、 groupsexpiresAfterも含まれます。

お客様がロールを追加したり、関数でのアクセス トークンのビルドを遅らせたりする必要がある場合は、 server SDK for C# を使用することをお勧めします。

[Function("WebPubSubConnectionCustomRoles")]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req)
{
    var serviceClient = new WebPubSubServiceClient(new Uri(endpoint), "<hub>", "<web-pubsub-connection-string>");
    var userId = req.Query["userid"].FirstOrDefault();
    // your method to get custom roles.
    var roles = GetRoles(userId);
    var url = await serviceClient.GetClientAccessUriAsync(TimeSpan.FromMinutes(5), userId, roles);
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.WriteString(url.ToString());
    return response;
}

お客様がロールを追加したり、関数でのアクセス トークンのビルドを遅らせたりする必要がある場合は、javaScript 用 server SDK を使用することをお勧めします

const { app } = require('@azure/functions');
const { WebPubSubServiceClient } = require('@azure/web-pubsub');
app.http('negotiate', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        const serviceClient = new WebPubSubServiceClient(process.env.WebPubSubConnectionString, "<hub>");
        let token = await serviceClient.getAuthenticationToken({ userId: req.query.userid, roles: ["webpubsub.joinLeaveGroup", "webpubsub.sendToGroup"] });
        return { body: token.url };
    },
});

この言語の完全なサンプルは保留中です

Java 用 Web PubSub 拡張機能はまだサポートされていません。

WebPubSubContext

// validate method when upstream set as http://<func-host>/api/{event}
[Function("validate")]
public static HttpResponseData Validate(
    [HttpTrigger(AuthorizationLevel.Anonymous, "options")] HttpRequestData req,
    [WebPubSubContextInput] WebPubSubContext wpsReq)
{
    return BuildHttpResponseData(req, wpsReq.Response);
}

// Respond AbuseProtection to put header correctly.
private static HttpResponseData BuildHttpResponseData(HttpRequestData request, SimpleResponse wpsResponse)
{
    var response = request.CreateResponse();
    response.StatusCode = (HttpStatusCode)wpsResponse.Status;
    response.Body = response.Body;
    foreach (var header in wpsResponse.Headers)
    {
        response.Headers.Add(header.Key, header.Value);
    }
    return response;
}
const { app, input } = require('@azure/functions');

const wpsContext = input.generic({
    type: 'webPubSubContext',
    name: 'wpsContext'
});

app.http('connect', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    extraInputs: [wpsContext],
    handler: async (request, context) => {
        var wpsRequest = context.extraInputs.get('wpsContext');

        return { "userId": wpsRequest.request.connectionContext.userId };
    }
});

この言語の完全なサンプルは保留中です

Java 用 Web PubSub 拡張機能はまだサポートされていません。

構成

次の表は、functions.json ファイルと WebPubSubContext 属性に設定したバインド構成のプロパティを説明しています。

function.json のプロパティ 属性のプロパティ 説明
タイプ 該当なし webPubSubContext に設定する必要があります。
方向 該当なし in に設定する必要があります。
名前 該当なし 入力 Web PubSub 要求の関数コードで使用される変数名。
接続 つながり 省略可能 - アップストリームの Azure Web PubSub サービスを指定するアプリ設定または設定コレクションの名前。 値は不正使用防止と署名検証に使用されます。 値は既定で "WebPubSubConnectionString" を使用して自動解決されます。 nullは、検証が必要ではなく、常に成功したことを意味します。

重要

最適なセキュリティを確保するために、関数アプリでは、共有シークレット キーを含む接続文字列を使用する代わりに、Web PubSub サービスに接続するときにマネージド ID を使用する必要があります。 詳細については、「 Microsoft Entra ID を使用してマネージド ID 要求を認証するを参照してください。

使用方法

WebPubSubContext には、次のプロパティが用意されています。

バインディング名 バインドの種類 説明 プロパティ
リクエスト WebPubSubEventRequest クライアントからの要求の詳細については、次の表を参照してください。 要求ヘッダーの WebPubSubConnectionContext と要求本文から逆シリアル化された他のプロパティでは要求を説明します (ReasonDisconnectedEventRequest など)。
応答 HttpResponseMessage 拡張機能によって、主に AbuseProtection とエラー ケースに対する応答が作成されます。 -
エラーメッセージ ひも アップストリーム要求を処理するときのエラーの詳細を説明します。 -
エラーがあります [bool] 有効な Web PubSub アップストリーム要求かどうかを示すフラグ。 -
isPreflight [bool] AbuseProtection のプレフライト要求かどうかを示すフラグ。 -

WebPubSubEventRequest の場合、要求シナリオに関するさまざまな情報を提供するさまざまなクラスに逆シリアル化されます。 PreflightRequest または無効なケースの場合、ユーザーは IsPreflight および HasError フラグを調べて確認できます。 システム ビルド応答 WebPubSubContext.Response を直接返すか、お客様が必要に応じてエラーをログに記録することをお勧めします。 さまざまなシナリオで、顧客は次のように要求プロパティを読み取ることができます。

派生クラス 説明 プロパティ
PreflightRequest AbuseProtectionIsPreflight の場合に で使用します -
ConnectEventRequest システム Connect イベントの種類で使用します Claims、Query、Subprotocols、ClientCertificates
ConnectedEventRequest システム Connected イベントの種類で使用します -
UserEventRequest ユーザー イベントの種類で使用します Data、DataType
DisconnectedEventRequest システム Disconnected イベントの種類で使用します 理由

WebPubSubContextは入力バインディングですが、HttpTriggerと比較してWebPubSubTrigger同様の要求逆シリアル化方法を提供しますが、制限があります。つまり、マージ後の接続状態はサポートされていません。 返される応答はサービス側で引き続き考慮されますが、ユーザーは自分で応答を作成する必要があります。 ユーザーがイベント応答を設定する必要がある場合は、HttpResponseMessage またはユーザー イベントのメッセージを含む ConnectEventResponse応答本文として返し、ce-connectionstate キーを含む接続状態を応答ヘッダーに配置する必要があります。