Socket.IO Azure Function trigger and binding (Preview)
This article explains how to use Socket.IO serverless integrate with Azure Functions.
Action | Binding Type |
---|---|
Get client negotiate result including url and access token | Input binding |
Triggered by messages from the service | Trigger binding |
Invoke service to send messages or manage clients | Output binding |
Source code | Package | API reference documentation | Product documentation | Samples
Important
Azure Function bindings can only integrate with Web PubSub for Socket.IO in Serverless Mode.
Authenticate and Connection String
In order to let the extension work with Web PubSub for Socket.IO, you need to provide either access keys or identity based configuration to authenticate with the service.
Access key based configuration
Configuration Name | Description |
---|---|
WebPubSubForSocketIOConnectionString | Required. Key based connection string to the service |
You can find the connection string in Keys blade in you Web PubSub for Socket.IO in the Azure portal.
For the local development, use the local.settings.json
file to store the connection string. Set WebPubSubForSocketIOConnectionString
to the connection string copied from the previous step:
{
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
`WebPubSubForSocketIOConnectionString`: "Endpoint=https://<webpubsub-name>.webpubsub.azure.com;AccessKey=<access-key>;Version=1.0;"
}
}
When deployed use the application settings to set the connection string.
Identity based configuration
Configuration Name | Description |
---|---|
WebPubSubForSocketIOConnectionString__endpoint | Required. The Endpoint of the service. For example, https://mysocketio.webpubsub.azure.com |
WebPubSubForSocketIOConnectionString__credential | Defines how a token should be obtained for the connection. This setting should be set to managedidentity if your deployed Azure Function intends to use managed identity authentication. This value is only valid when a managed identity is available in the hosting environment. |
WebPubSubForSocketIOConnectionString__clientId | When credential is set to managedidentity , this property can be set to specify the user-assigned identity to be used when obtaining a token. The property accepts a client ID corresponding to a user-assigned identity assigned to the application. If not specified, the system-assigned identity is used. |
The function binding follows the common properties for identity based configuration. See Common properties for identity-based connections for more unmentioned properties.
For the local development, use the local.settings.json
file to store the connection string. Set WebPubSubForSocketIOConnectionString
to the connection string copied from the previous step:
{
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"WebPubSubForSocketIOConnectionString__endpoint": "https://<webpubsub-name>.webpubsub.azure.com",
"WebPubSubForSocketIOConnectionString__tenant": "<tenant id you're in>",
}
}
If you want to use identity based configuration and running online, the AzureWebJobsStorage
should refer to Connecting to host storage with an identity.
Input Binding
Socket.IO Input binding generates a SocketIONegotiationResult
to the client negotiation request. When a Socket.IO client tries to connect to the service, it needs to know the endpoint
, path
, and access token
for authentication. It's a common practice to have a server to generate these data, which is called negotiation.
[FunctionName("SocketIONegotiate")]
public static IActionResult Negotiate(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req,
[SocketIONegotiation(Hub = "hub", UserId = "userId")] SocketIONegotiationResult result)
{
return new OkObjectResult(result);
}
Attribute
The attribute for input binding is [SocketIONegotiation]
.
Attribute property | Description |
---|---|
Hub | The hub name that a client needs to connect to. |
Connection | The name of the app setting that contains the Socket.IO connection string (defaults to WebPubSubForSocketIOConnectionString ). |
UserId | The userId of the connection. It applies to all sockets in the connection. It becomes the sub claim in the generated token. |
Trigger Binding
Azure Function uses trigger binding to trigger a function to process the events from the Web PubSub for Socket.IO.
Trigger binding exposes a specific path followed the Azure Function endpoint. The url should be set as the URL Template of the service (Portal: settings -> event handler -> URL Template). In the endpoint pattern, the query part code=<API_KEY>
is REQUIRED when you're using Azure Function App for security reasons. The key can be found in Azure portal. Find your function app resource and navigate to Functions -> App keys -> System keys -> socketio_extension after you deploy the function app to Azure. Though, this key isn't needed when you're working with local functions.
<Function_App_Endpoint>/runtime/webhooks/socketio?code=<API_KEY>
Function triggers for socket connect event.
[FunctionName("SocketIOTriggerConnect")]
public static async Task<SocketIOEventHandlerResponse> Connect(
[SocketIOTrigger("hub", "connect")] SocketIOConnectRequest request)
{
return new SocketIOConnectResponse();
}
Function triggers for socket connected event.
[FunctionName("SocketIOTriggerConnected")]
public static async Task Connected(
[SocketIOTrigger("hub", "connected")] SocketIOConnectedRequest request)
{
}
Function triggers for socket disconnect event.
[FunctionName("SocketIOTriggerDisconnected")]
public static async Task Disconnected(
[SocketIOTrigger("hub", "disconnected")] SocketIODisconnectedRequest request)
{
}
Function triggers for normal messages from clients.
[FunctionName("SocketIOTriggerMessage")]
public static async Task NewMessage(
[SocketIOTrigger("hub", "new message")] SocketIOMessageRequest request,
[SocketIOParameter] string arg)
{
}
Attributes
The attribute for trigger binding is [SocketIOTrigger]
.
Attribute property | Description |
---|---|
Hub | The hub name that a client needs to connect to. |
Namespace | The namespace of the socket. Default: "/" |
EventName | The event name that the function triggers for. Some event names are predefined: connect for socket connect event. connected for socket connected event. disconnected for socket disconnected event. And other events are defined by user and it need to match the event name sent by client side. |
ParameterNames | The parameter name list of the event. The length of list should be consistent with event sent from client. And the name uses the Binding expressions and access by the same-name function parameter. |
Binding Data
[SocketIOTrigger]
binds some variables to binding data. You can learn more about it from Azure Functions binding expression patterns
SocketIOAttribute
SocketIOAttribute
is an alternative of ParameterNames
, which simplifies the function definition. For example, the following two definitions have the same effect:
[FunctionName("SocketIOTriggerMessage")]
public static async Task NewMessage(
[SocketIOTrigger("hub", "new message")] SocketIOMessageRequest request,
[SocketIOParameter] string arg)
{
}
[FunctionName("SocketIOTriggerMessage")]
public static async Task NewMessage(
[SocketIOTrigger("hub", "new message", ParameterNames = new[] {"arg"})] SocketIOMessageRequest request,
string arg)
{
}
Note that ParameterNames
and [SocketIOParameter]
can't be used together.
Request of Input Binding
The data structure of input binding arguments varies depending on the message type.
Connect
{
"namespace": "",
"socketId": "",
"claims": {
"<claim-type>": [ "<claim-value>" ]
},
"query": {
"<query-key>": [ "<query-value>" ]
},
"headers":{
"<header-name>": [ "<header-value>" ]
},
"clientCertificates":{
{
"thumbprint": "",
"content": ""
}
}
}
Property | Description |
---|---|
namespace | The namespace of the socket. |
socketId | The unique identity of the socket. |
claims | The claim of JWT of the client connection. Note, it's not the JWT when the service request the function, but the JWT when the Engine.IO client connects to the service. |
query | The query of the client connection. Note, it's not the query when the service request the function, but the query when the Engine.IO client connects to the service. |
headers | The headers of the client connection. Note, it's not the headers when the service request the function, but the headers when the Engine.IO client connects to the service. |
clientCertificates | The client certificate if it's enabled |
Connected
{
"namespace": "",
"socketId": "",
}
Property | Description |
---|---|
namespace | The namespace of the socket. |
socketId | The unique identity of the socket. |
Disconnected
{
"namespace": "",
"socketId": "",
"reason": ""
}
Property | Description |
---|---|
namespace | The namespace of the socket. |
socketId | The unique identity of the socket. |
reason | The connection close reason description. |
Normal events
{
"namespace": "",
"socketId": "",
"payload": "",
"eventName": "",
"parameters": []
}
Property | Description |
---|---|
namespace | The namespace of the socket. |
socketId | The unique identity of the socket. |
payload | The message payload in Engine.IO protocol |
eventName | The event name of the request. |
parameters | List of parameters of the message. |
Output Binding
The output binding currently support the following functionality:
- Add a socket to room
- Remove a socket from room
- Send messages to a socket
- Send messages to a room
- Send messages to a namespace
- Disconnect sockets
[FunctionName("SocketIOOutput")]
public static async Task<IActionResult> SocketIOOutput(
[SocketIOTrigger("hub", "new message")] SocketIOMessageRequest request,
[SocketIO(Hub = "hub")] IAsyncCollector<SocketIOAction> collector)
{
await collector.AddAsync(SocketIOAction.CreateSendToNamespaceAction("new message", new[] { "arguments" }));
}
Attribute
The attribute for input binding is [SocketIO]
.
Attribute property | Description |
---|---|
Hub | The hub name that a client needs to connect to. |
Connection | The name of the app setting that contains the Socket.IO connection string (defaults to WebPubSubForSocketIOConnectionString ). |
Actions
Output binding uses actions to perform operations. Currently, we support the following actions:
AddSocketToRoomAction
{
"type": "AddSocketToRoom",
"socketId": "",
"room": ""
}
RemoveSocketFromRoomAction
{
"type": "RemoveSocketFromRoom",
"socketId": "",
"room": ""
}
SendToNamespaceAction
{
"type": "SendToNamespace",
"eventName": "",
"parameters": [],
"exceptRooms": []
}
SendToRoomsAction
{
"type": "SendToRoom",
"eventName": "",
"parameters": [],
"rooms": [],
"exceptRooms": []
}
SendToSocketAction
{
"type": "SendToSocket",
"eventName": "",
"parameters": [],
"socketId": ""
}
DisconnectSocketsAction
{
"type": "DisconnectSockets",
"rooms": [],
"closeUnderlyingConnection": false
}