扩展提供两个输入绑定,以满足不同的需求。
-
客户端在连接到 Azure Web PubSub 服务之前,必须知道服务终结点 URL 和有效的访问令牌。
WebPubSubConnection输入绑定会生成所需信息,因此客户端无需自行处理令牌生成。 令牌受时间限制,可以对特定用户进行连接身份验证。 因此,不要缓存令牌或在客户端之间共享令牌。 客户端可以使用处理此输入绑定的 HTTP 触发器来检索连接信息。 -
使用静态 Web 应用时,
HttpTrigger是唯一受支持的触发器。 在 Web PubSub 方案中,WebPubSubContext输入绑定可帮助用户在 Web PubSub 协议下反序列化来自服务的上游 HTTP 请求。 因此,客户可获得与WebPubSubTrigger相似的结果,从而在函数中轻松处理。 使用HttpTrigger时,客户需要在事件处理程序相应地配置 HttpTrigger 的公开 URL。
WebPubSubConnection
Example
以下示例演示了一个 HTTP 触发器函数,该函数使用输入绑定获取 Web PubSub 连接信息,并通过 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/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 声明。 可以轻松地使用应用服务身份验证向函数应用添加身份验证。
应用服务身份验证会设置名为 x-ms-client-principal-id 和 x-ms-client-principal-name(分别包含经身份验证的用户的客户端主体 ID 和名称)的 HTTP 标头。
可以使用绑定表达式将绑定的属性设置为 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/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 属性 | Attribute 属性 | Description |
|---|---|---|
| type | n/a | 必须设置为 webPubSubConnection |
| direction | n/a | 必须设置为 in |
| name | n/a | 变量名称,在输入连接绑定对象的函数代码中使用。 |
| 集线器 | 集线器 | 必需 - 该值必须设置为 Web PubSub Hub 的名称,以触发函数。 支持在特性中将该值设置为更高优先级,或者在应用设置中将该值设置为全局值。 |
| userId | UserId | 可选 - 用户标识符声明的值,将在访问密钥令牌中设置。 |
| clientProtocol | ClientProtocol | 可选 - 客户端协议类型。 有效值包括 default 和 mqtt。 对于 MQTT 客户端,必须将它设置为 mqtt. 对于其他客户端,可以省略属性或将其设置为 default。 |
| 连接 | 连接 | 必需 - 应用设置的名称,包含 Web PubSub 服务连接字符串(默认为“WebPubSubConnectionString”)。 |
使用情况
WebPubSubConnection 提供以下属性。
| 绑定名称 | 绑定类型 | Description |
|---|---|---|
| BaseUri | Uri | Web PubSub 客户端连接 URI。 |
| Uri | Uri | Web PubSub 连接的绝对 URI,包含根据请求生成的 AccessToken。 |
| AccessToken | 字符串 | 根据请求的用户ID和服务信息生成的AccessToken。 |
WebPubSubConnection 提供以下属性。
| 绑定名称 | Description |
|---|---|
| baseUrl | Web PubSub 客户端连接 URI。 |
| url | Web PubSub 连接的绝对 URI,包含根据请求生成的 AccessToken。 |
| accessToken | 根据请求的用户ID和服务信息生成的AccessToken。 |
注释
尚不支持适用于 Java 的 Web PubSub 扩展。
对生成的令牌进行更多自定义
仅限于绑定参数类型不支持传递列表或数组,这意味着WebPubSubConnection并不完全支持服务器 SDK 的所有参数,尤其是roles,并且还包括groups和expiresAfter。
当客户需要在函数中添加角色或延迟生成访问令牌时,建议使用 适用于 C# 的服务器 SDK。
[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 的服务器 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
Example
// 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 属性 | Attribute 属性 | Description |
|---|---|---|
| type | n/a | 必须设置为 webPubSubContext。 |
| direction | n/a | 必须设置为 in。 |
| name | n/a | 在函数代码中使用的变量名称,用于输入 Web PubSub 请求。 |
| connections | 连接 | 可选 - 应用设置名称或设置集合前缀的数组,用于标识上游Azure Web PubSub服务连接。 这些值用于滥用保护和签名验证。 如果未指定,请回退到全局 WebPubSubConnectionString 应用设置。 如果未配置验证,则会跳过验证并接受所有请求。例子: ["CustomWebPubSubConnection1", "CustomWebPubSubConnection2"] |
Important
为了获得最佳安全性,函数应用在连接到 Web PubSub 服务时应使用托管标识,而不是使用包含共享密钥的连接字符串。 有关详细信息,请参阅 使用 Microsoft Entra ID 授权托管标识请求。
使用情况
WebPubSubContext 提供以下属性。
| 绑定名称 | 绑定类型 | Description | 属性 |
|---|---|---|---|
| 申请 | WebPubSubEventRequest |
从客户端请求,有关详细信息,请参阅下表。 | 请求标头中的 WebPubSubConnectionContext 和从请求正文反序列化的其他属性用于描述请求,例如 Reason 的 DisconnectedEventRequest。 |
| 响应 | HttpResponseMessage |
扩展生成响应,主要针对 AbuseProtection 和错误情况。 |
- |
| errorMessage | 字符串 | 描述处理上游请求时的错误详细信息。 | - |
| 有错误 | bool | 指示其是否是有效 Web PubSub 上游请求的标志。 | - |
| isPreflight | bool | 指示其是否是 AbuseProtection 的预检请求的标志。 |
- |
对于 WebPubSubEventRequest,会将其反序列化为不同的类,从而提供关于请求场景的不同信息。 对于 PreflightRequest 或无效的情况,用户可以检查标志 IsPreflight 和 HasError 来了解情况。 我们建议你直接返回系统生成响应 WebPubSubContext.Response ,或者客户可以按需记录错误。 在不同方案中,客户可以按如下所示读取请求属性。
| 派生类 | Description | 属性 |
|---|---|---|
PreflightRequest |
当 AbuseProtection 为 IsPreflight 时,在 中使用 |
- |
ConnectEventRequest |
在系统 Connect 事件类型中使用 |
权利声明、查询、子协议、客户证书 |
ConnectedEventRequest |
在系统 Connected 事件类型中使用 |
- |
UserEventRequest |
在用户事件类型中使用 | 数据 (Data)、数据类型 (DataType) |
DisconnectedEventRequest |
在系统 Disconnected 事件类型中使用 |
原因 |
注释
WebPubSubContext尽管这是一个输入绑定,但在HttpTrigger比较中WebPubSubTrigger提供了类似的请求反序列化方式,但存在限制,即不支持合并后的连接状态。 服务端仍然会遵守返回响应,但用户需要自己构建响应。 如果用户需要设置事件响应,应返回一个包含或用户事件消息的 作为响应体,并在响应头中使用键 设置连接状态。