Skip to content

Commit e6ecf62

Browse files
authored
Merge pull request #105048 from craigshoemaker/crs-functions-signalr-restructure
SignalR Service binding ref restructure
2 parents 6d40b71 + 41684c3 commit e6ecf62

File tree

5 files changed

+1062
-1008
lines changed

5 files changed

+1062
-1008
lines changed

articles/azure-functions/TOC.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,16 @@
389389
- name: Output
390390
href: functions-bindings-service-bus-output.md
391391
- name: SignalR Service
392-
href: functions-bindings-signalr-service.md
392+
items:
393+
- name: Overview
394+
href: functions-bindings-signalr-service.md
395+
displayName: SignalR Service
396+
- name: Overview
397+
href: functions-bindings-signalr-service-input.md
398+
displayName: SignalR Service
399+
- name: Overview
400+
href: functions-bindings-signalr-service-output.md
401+
displayName: SignalR Service
393402
- name: Table storage
394403
href: functions-bindings-storage-table.md
395404
- name: Timer
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
---
2+
title: Azure Functions SignalR Service input binding
3+
description: Learn to return a SignalR service endpoint URL and access token in Azure Functions.
4+
author: craigshoemaker
5+
ms.topic: reference
6+
ms.date: 02/20/2020
7+
ms.author: cshoe
8+
---
9+
10+
# SignalR Service input binding for Azure Functions
11+
12+
Before a client can connect to Azure SignalR Service, it must retrieve the service endpoint URL and a valid access token. The *SignalRConnectionInfo* input binding produces the SignalR Service endpoint URL and a valid token that are used to connect to the service. Because the token is time-limited and can be used to authenticate a specific user to a connection, you should not cache the token or share it between clients. An HTTP trigger using this binding can be used by clients to retrieve the connection information.
13+
14+
For more information on how this binding is used to create a "negotiate" function that can be consumed by a SignalR client SDK, see the [Azure Functions development and configuration article](../azure-signalr/signalr-concept-serverless-development-config.md) in the SignalR Service concepts documentation.
15+
16+
For information on setup and configuration details, see the [overview](functions-bindings-signalr-service.md).
17+
18+
## Example
19+
20+
# [C#](#tab/csharp)
21+
22+
The following example shows a [C# function](functions-dotnet-class-library.md) that acquires SignalR connection information using the input binding and returns it over HTTP.
23+
24+
```cs
25+
[FunctionName("negotiate")]
26+
public static SignalRConnectionInfo Negotiate(
27+
[HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req,
28+
[SignalRConnectionInfo(HubName = "chat")]SignalRConnectionInfo connectionInfo)
29+
{
30+
return connectionInfo;
31+
}
32+
```
33+
34+
# [C# Script](#tab/csharp-script)
35+
36+
The following example shows a SignalR connection info input binding in a *function.json* file and a [C# Script function](functions-reference-csharp.md) that uses the binding to return the connection information.
37+
38+
Here's binding data in the *function.json* file:
39+
40+
Example function.json:
41+
42+
```json
43+
{
44+
"type": "signalRConnectionInfo",
45+
"name": "connectionInfo",
46+
"hubName": "chat",
47+
"connectionStringSetting": "<name of setting containing SignalR Service connection string>",
48+
"direction": "in"
49+
}
50+
```
51+
52+
Here's the C# Script code:
53+
54+
```cs
55+
#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
56+
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
57+
58+
public static SignalRConnectionInfo Run(HttpRequest req, SignalRConnectionInfo connectionInfo)
59+
{
60+
return connectionInfo;
61+
}
62+
```
63+
64+
# [JavaScript](#tab/javascript)
65+
66+
The following example shows a SignalR connection info input binding in a *function.json* file and a [JavaScript function](functions-reference-node.md) that uses the binding to return the connection information.
67+
68+
Here's binding data in the *function.json* file:
69+
70+
Example function.json:
71+
72+
```json
73+
{
74+
"type": "signalRConnectionInfo",
75+
"name": "connectionInfo",
76+
"hubName": "chat",
77+
"connectionStringSetting": "<name of setting containing SignalR Service connection string>",
78+
"direction": "in"
79+
}
80+
```
81+
82+
Here's the JavaScript code:
83+
84+
```javascript
85+
module.exports = async function (context, req, connectionInfo) {
86+
context.res.body = connectionInfo;
87+
};
88+
```
89+
90+
# [Python](#tab/python)
91+
92+
The following example shows a SignalR connection info input binding in a *function.json* file and a [Python function](functions-reference-python.md) that uses the binding to return the connection information.
93+
94+
Here's binding data in the *function.json* file:
95+
96+
Example function.json:
97+
98+
```json
99+
{
100+
"type": "signalRConnectionInfo",
101+
"name": "connectionInfo",
102+
"hubName": "chat",
103+
"connectionStringSetting": "<name of setting containing SignalR Service connection string>",
104+
"direction": "in"
105+
}
106+
```
107+
108+
Here's the Python code:
109+
110+
```python
111+
def main(req: func.HttpRequest, connectionInfoJson: str) -> func.HttpResponse:
112+
return func.HttpResponse(
113+
connectionInfoJson,
114+
status_code=200,
115+
headers={
116+
'Content-type': 'application/json'
117+
}
118+
)
119+
```
120+
121+
# [Java](#tab/java)
122+
123+
The following example shows a [Java function](functions-reference-java.md) that acquires SignalR connection information using the input binding and returns it over HTTP.
124+
125+
```java
126+
@FunctionName("negotiate")
127+
public SignalRConnectionInfo negotiate(
128+
@HttpTrigger(
129+
name = "req",
130+
methods = { HttpMethod.POST },
131+
authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
132+
@SignalRConnectionInfoInput(
133+
name = "connectionInfo",
134+
hubName = "chat") SignalRConnectionInfo connectionInfo) {
135+
return connectionInfo;
136+
}
137+
```
138+
139+
---
140+
141+
## Authenticated tokens
142+
143+
If the function is triggered by an authenticated client, you can add a user ID claim to the generated token. You can easily add authentication to a function app using [App Service Authentication](../app-service/overview-authentication-authorization.md).
144+
145+
App Service Authentication sets HTTP headers named `x-ms-client-principal-id` and `x-ms-client-principal-name` that contain the authenticated user's client principal ID and name, respectively.
146+
147+
# [C#](#tab/csharp)
148+
149+
You can set the `UserId` property of the binding to the value from either header using a [binding expression](./functions-bindings-expressions-patterns.md): `{headers.x-ms-client-principal-id}` or `{headers.x-ms-client-principal-name}`.
150+
151+
```cs
152+
[FunctionName("negotiate")]
153+
public static SignalRConnectionInfo Negotiate(
154+
[HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req,
155+
[SignalRConnectionInfo
156+
(HubName = "chat", UserId = "{headers.x-ms-client-principal-id}")]
157+
SignalRConnectionInfo connectionInfo)
158+
{
159+
// connectionInfo contains an access key token with a name identifier claim set to the authenticated user
160+
return connectionInfo;
161+
}
162+
```
163+
164+
# [C# Script](#tab/csharp-script)
165+
166+
You can set the `userId` property of the binding to the value from either header using a [binding expression](./functions-bindings-expressions-patterns.md): `{headers.x-ms-client-principal-id}` or `{headers.x-ms-client-principal-name}`.
167+
168+
Example function.json:
169+
170+
```json
171+
{
172+
"type": "signalRConnectionInfo",
173+
"name": "connectionInfo",
174+
"hubName": "chat",
175+
"userId": "{headers.x-ms-client-principal-id}",
176+
"connectionStringSetting": "<name of setting containing SignalR Service connection string>",
177+
"direction": "in"
178+
}
179+
```
180+
181+
Here's the C# Script code:
182+
183+
```cs
184+
#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
185+
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
186+
187+
public static SignalRConnectionInfo Run(HttpRequest req, SignalRConnectionInfo connectionInfo)
188+
{
189+
// connectionInfo contains an access key token with a name identifier
190+
// claim set to the authenticated user
191+
return connectionInfo;
192+
}
193+
```
194+
195+
# [JavaScript](#tab/javascript)
196+
197+
You can set the `userId` property of the binding to the value from either header using a [binding expression](./functions-bindings-expressions-patterns.md): `{headers.x-ms-client-principal-id}` or `{headers.x-ms-client-principal-name}`.
198+
199+
Example function.json:
200+
201+
```json
202+
{
203+
"type": "signalRConnectionInfo",
204+
"name": "connectionInfo",
205+
"hubName": "chat",
206+
"userId": "{headers.x-ms-client-principal-id}",
207+
"connectionStringSetting": "<name of setting containing SignalR Service connection string>",
208+
"direction": "in"
209+
}
210+
```
211+
212+
Here's the JavaScript code:
213+
214+
```javascript
215+
module.exports = async function (context, req, connectionInfo) {
216+
// connectionInfo contains an access key token with a name identifier
217+
// claim set to the authenticated user
218+
context.res.body = connectionInfo;
219+
};
220+
```
221+
222+
# [Python](#tab/python)
223+
224+
You can set the `userId` property of the binding to the value from either header using a [binding expression](./functions-bindings-expressions-patterns.md): `{headers.x-ms-client-principal-id}` or `{headers.x-ms-client-principal-name}`.
225+
226+
Example function.json:
227+
228+
```json
229+
{
230+
"type": "signalRConnectionInfo",
231+
"name": "connectionInfo",
232+
"hubName": "chat",
233+
"userId": "{headers.x-ms-client-principal-id}",
234+
"connectionStringSetting": "<name of setting containing SignalR Service connection string>",
235+
"direction": "in"
236+
}
237+
```
238+
239+
Here's the Python code:
240+
241+
```python
242+
def main(req: func.HttpRequest, connectionInfoJson: str) -> func.HttpResponse:
243+
# connectionInfo contains an access key token with a name identifier
244+
# claim set to the authenticated user
245+
return func.HttpResponse(
246+
connectionInfoJson,
247+
status_code=200,
248+
headers={
249+
'Content-type': 'application/json'
250+
}
251+
)
252+
```
253+
254+
# [Java](#tab/java)
255+
256+
You can set the `userId` property of the binding to the value from either header using a [binding expression](./functions-bindings-expressions-patterns.md): `{headers.x-ms-client-principal-id}` or `{headers.x-ms-client-principal-name}`.
257+
258+
```java
259+
@FunctionName("negotiate")
260+
public SignalRConnectionInfo negotiate(
261+
@HttpTrigger(
262+
name = "req",
263+
methods = { HttpMethod.POST },
264+
authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
265+
@SignalRConnectionInfoInput(
266+
name = "connectionInfo",
267+
hubName = "chat",
268+
userId = "{headers.x-ms-client-principal-id}") SignalRConnectionInfo connectionInfo) {
269+
return connectionInfo;
270+
}
271+
```
272+
273+
---
274+
275+
## Next steps
276+
277+
- [Send SignalR Service messages (Output binding)](./functions-bindings-signalr-service-output.md)

0 commit comments

Comments
 (0)