Enlace de entrada de SignalR Service para Azure Functions

Para que un cliente pueda conectarse a Azure SignalR Service, antes debe recuperar la dirección URL del punto de conexión del servicio y un token de acceso válido. El enlace de entrada SignalRConnectionInfo genera la dirección URL del punto de conexión de SignalR Service y un token válido que se usan para conectarse al servicio. El token tiene una limitación temporal y se puede usar para autenticar un usuario concreto en una conexión. Por lo tanto, no debe almacenar en caché el token ni compartirlo entre clientes. Normalmente, se usa SignalRConnectionInfo con un desencadenador HTTP para que los clientes recuperen la información de conexión.

Para obtener más información sobre cómo usar este enlace para crear una función "negotiate" compatible con un SDK de cliente de SignalR, consulte Desarrollo y configuración de Azure Functions con Azure SignalR Service. Para obtener información sobre los detalles de instalación y configuración, vea la información general.

Ejemplo

Se puede crear una función C# mediante uno de los siguientes modos de C#:

  • Modelo de trabajo aislado: función compilada en C# que se ejecuta en un proceso trabajador aislado del tiempo de ejecución. Se requiere un proceso de trabajo aislado para admitir funciones de C# ejecutándose en versiones de .NET que son y no son LTS y .NET Framework.
  • Modelo en curso: función C# compilada que se ejecuta en el mismo proceso que el tiempo de ejecución de Functions.
  • Script de C#: se usa principalmente al crear funciones de C# en Azure Portal.

En el siguiente ejemplo se muestra una función de C# que adquiere la información de la conexión de SignalR mediante el enlace de entrada y la devuelve a través de HTTP.

[Function(nameof(Negotiate))]
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "serverless")] string connectionInfo)
{
    // The serialization of the connection info object is done by the framework. It should be camel case. The SignalR client respects the camel case response only.
    return connectionInfo;
}

En el ejemplo siguiente se muestra un enlace de entrada de la información de la conexión de SignalR en un archivo function.json y una función que usa el enlace para devolver la información de conexión.

Estos son los datos de enlace para el ejemplo del archivo function.json:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "hubName1",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

Este es el código de JavaScript:

const { app, input } = require('@azure/functions');

const inputSignalR = input.generic({
    type: 'signalRConnectionInfo',
    name: 'connectionInfo',
    hubName: 'hubName1',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

app.post('negotiate', {
    authLevel: 'function',
    handler: (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get(inputSignalR)) }
    },
    route: 'negotiate',
    extraInputs: [inputSignalR],
});

Los ejemplos completos de PowerShell están pendientes.

En el ejemplo siguiente se muestra un enlace de entrada de la información de la conexión de SignalR en un archivo function.json y una función de Python que usa el enlace para devolver la información de conexión.

Este es el código de Python:

def main(req: func.HttpRequest, connectionInfoJson: str) -> func.HttpResponse:
    return func.HttpResponse(
        connectionInfoJson,
        status_code=200,
        headers={
            'Content-type': 'application/json'
        }
    )

En el siguiente ejemplo se muestra una función de Java que adquiere la información de la conexión de SignalR mediante el enlace de entrada y la devuelve a través de HTTP.

@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(
            name = "connectionInfo",
            HubName = "hubName1") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

Uso

Tokens autenticados

Cuando un cliente autenticado desencadena la función, puede agregar una notificación del identificador de usuario al token generado. Puede agregar fácilmente la autenticación a una aplicación de función mediante Autenticación de App Service.

La autenticación de App Service establece encabezados HTTP denominados x-ms-client-principal-id y x-ms-client-principal-name que contienen el identificador y el nombre de la entidad de seguridad de cliente del usuario autenticado, respectivamente.

Puede establecer la propiedad UserId del enlace en el valor de cualquier encabezado mediante una expresión de enlace: {headers.x-ms-client-principal-id} o {headers.x-ms-client-principal-name}.

[Function("Negotiate")]
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "hubName1", UserId = "{headers.x-ms-client-principal-id}")] string connectionInfo)
{
    // The serialization of the connection info object is done by the framework. It should be camel case. The SignalR client respects the camel case response only.
    return connectionInfo;
}
@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST, HttpMethod.GET },
            authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(name = "connectionInfo", hubName = "hubName1", userId = "{headers.x-ms-signalr-userid}") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

Estos son los datos de enlace del archivo function.json:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "hubName1",
    "userId": "{headers.x-ms-client-principal-id}",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

Este es el código de JavaScript:

const { app, input } = require('@azure/functions');

const inputSignalR = input.generic({
    type: 'signalRConnectionInfo',
    name: 'connectionInfo',
    hubName: 'hubName1',
    connectionStringSetting: 'AzureSignalRConnectionString',
    userId: '{headers.x-ms-client-principal-id}',
});

app.post('negotiate', {
    authLevel: 'function',
    handler: (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get(inputSignalR)) }
    },
    route: 'negotiate',
    extraInputs: [inputSignalR],
});

Los ejemplos completos de PowerShell están pendientes.

Este es el código de Python:

def main(req: func.HttpRequest, connectionInfo: str) -> func.HttpResponse:
    # connectionInfo contains an access key token with a name identifier
    # claim set to the authenticated user
    return func.HttpResponse(
        connectionInfo,
        status_code=200,
        headers={
            'Content-type': 'application/json'
        }
    )
@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(
            name = "connectionInfo",
            HubName = "hubName1",
            userId = "{headers.x-ms-client-principal-id}") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

Atributos

Las bibliotecas de C# en proceso y de proceso de trabajo aislado usan atributos para definir la función. El script de C#, en su lugar, usa un archivo de configuración function.json.

En la siguiente tabla se detallan las propiedades del atributo SignalRConnectionInfoInput:

Propiedad de atributo Descripción
HubName Necesario. Nombre del centro.
ConnectionStringSetting El nombre de la configuración de la aplicación que contiene la cadena de conexión de SignalR Service, que de manera predeterminada es AzureSignalRConnectionString.
UserId Opcional. Identificador de usuario de una conexión de SignalR. Puede usar una expresión de enlace para enlazar el valor a una consulta o encabezado de solicitud HTTP.
IdToken Opcional. Un token JWT cuyas notificaciones se agregarán a las notificaciones del usuario. Debe usarse junto con ClaimTypeList. Puede usar una expresión de enlace para enlazar el valor a una consulta o encabezado de solicitud HTTP.
ClaimTypeList Opcional. Lista de tipos de notificación, que filtran las notificaciones en IdToken.

anotaciones

En la tabla siguiente se explica la configuración admitida para la anotación SignalRConnectionInfoInput.

Configuración Descripción
name Nombre de la variable que se utiliza en el código de función para el objeto de información de conexión.
hubName Necesario. Nombre del centro.
connectionStringSetting El nombre de la configuración de la aplicación que contiene la cadena de conexión de SignalR Service, que de manera predeterminada es AzureSignalRConnectionString.
userId Opcional. Identificador de usuario de una conexión de SignalR. Puede usar una expresión de enlace para enlazar el valor a una consulta o encabezado de solicitud HTTP.
idToken Opcional. Un token JWT cuyas notificaciones se agregarán a las notificaciones del usuario. Debe usarse junto con claimTypeList. Puede usar una expresión de enlace para enlazar el valor a una consulta o encabezado de solicitud HTTP.
claimTypeList Opcional. Lista de tipos de notificación, que filtra las notificaciones en IdToken.

anotaciones

En la tabla siguiente se explica la configuración admitida para la anotación SignalRConnectionInfoInput.

Configuración Descripción
name Nombre de la variable que se utiliza en el código de función para el objeto de información de conexión.
hubName Necesario. Nombre del centro.
connectionStringSetting El nombre de la configuración de la aplicación que contiene la cadena de conexión de SignalR Service, que de manera predeterminada es AzureSignalRConnectionString.
userId Opcional. Identificador de usuario de una conexión de SignalR. Puede usar una expresión de enlace para enlazar el valor a una consulta o encabezado de solicitud HTTP.
idToken Opcional. Un token JWT cuyas notificaciones se agregarán a las notificaciones del usuario. Debe usarse junto con claimTypeList. Puede usar una expresión de enlace para enlazar el valor a una consulta o encabezado de solicitud HTTP.
claimTypeList Opcional. Lista de tipos de notificación, que filtra las notificaciones en IdToken.

Configuración

En la siguiente tabla se explican las propiedades de configuración de enlace que se establecen en el archivo function.json.

Propiedad de function.json Descripción
type Se debe establecer en signalRConnectionInfo.
direction Se debe establecer en in.
hubName Necesario. Nombre del centro.
connectionStringSetting El nombre de la configuración de la aplicación que contiene la cadena de conexión de SignalR Service, que de manera predeterminada es AzureSignalRConnectionString.
userId Opcional. Identificador de usuario de una conexión de SignalR. Puede usar una expresión de enlace para enlazar el valor a una consulta o encabezado de solicitud HTTP.
idToken Opcional. Un token JWT cuyas notificaciones se agregarán a las notificaciones del usuario. Debe usarse junto con claimTypeList. Puede usar una expresión de enlace para enlazar el valor a una consulta o encabezado de solicitud HTTP.
claimTypeList Opcional. Lista de tipos de notificación, que filtra las notificaciones en IdToken.

Expresiones de enlace para un desencadenador HTTP

Es un escenario común que los valores de algunos atributos del enlace de entrada de SignalR proceden de solicitudes HTTP. Por lo tanto, se muestra cómo enlazar valores de solicitudes HTTP a atributos de enlace de entrada de SignalR a través de una expresión de enlace.

Tipo de metadatos HTTP Formato de expresiones de enlace Descripción Ejemplo
Consulta de solicitud HTTP {query.QUERY_PARAMETER_NAME} Enlaza el valor del parámetro de consulta correspondiente a un atributo {query.userName}
El encabezado de la solicitud HTTP {headers.HEADER_NAME} Enlaza el valor de un encabezado a un atributo {headers.token}

Pasos siguientes