azure_functions/bindings/signalr_connection_info.rs
1use crate::{
2 http::Body,
3 rpc::{typed_data::Data, TypedData},
4};
5use serde::{Deserialize, Serialize};
6use serde_json::{from_str, to_string};
7use std::borrow::Cow;
8
9/// Represents the SignalR connection information input binding.
10///
11/// The following binding attributes are supported:
12///
13/// | Name | Description |
14/// |--------------|------------------------------------------------------------------------------------------------------------------------------|
15/// | `name` | The name of the parameter being bound. |
16/// | `hub_name` | The name of the SignalR hub for which the connection information is generated. |
17/// | `user_id` | The value of the user identifier claim to be set in the access key token (optional). |
18/// | `connection` | The name of the app setting that contains the SignalR Service connection string. Defaults to `AzureSignalRConnectionString`. |
19///
20/// # Examples
21///
22/// This example implements an HTTP-triggered Azure Function that returns SignalR connection information:
23///
24/// ```rust
25/// use azure_functions::{
26/// bindings::{HttpRequest, HttpResponse, SignalRConnectionInfo},
27/// func,
28/// };
29///
30/// #[func]
31/// #[binding(name = "_req", auth_level = "anonymous")]
32/// #[binding(
33/// name = "info",
34/// hub_name = "chat",
35/// user_id = "{headers.x-ms-signalr-userid}",
36/// connection = "myconnection"
37/// )]
38/// pub fn negotiate(_req: HttpRequest, info: SignalRConnectionInfo) -> HttpResponse {
39/// info.into()
40/// }
41/// ```
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[serde(rename_all = "camelCase")]
44pub struct SignalRConnectionInfo {
45 /// The endpoint URL for the SignalR service.
46 pub url: String,
47 /// The access token for the SignalR service.
48 pub access_token: String,
49}
50
51#[doc(hidden)]
52impl From<TypedData> for SignalRConnectionInfo {
53 fn from(data: TypedData) -> Self {
54 match &data.data {
55 Some(Data::Json(s)) => from_str(s).expect("failed to parse SignalR connection info"),
56 _ => panic!("expected JSON data for SignalR connection info"),
57 }
58 }
59}
60
61impl<'a> Into<Body<'a>> for SignalRConnectionInfo {
62 fn into(self) -> Body<'a> {
63 Body::Json(Cow::from(
64 to_string(&self).expect("failed to serialize SignalR connection info"),
65 ))
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn it_serializes_to_json() {
75 let json = to_string(&SignalRConnectionInfo {
76 url: "foo".to_owned(),
77 access_token: "bar".to_owned(),
78 })
79 .unwrap();
80
81 assert_eq!(json, r#"{"url":"foo","accessToken":"bar"}"#);
82 }
83
84 #[test]
85 fn it_converts_from_typed_data() {
86 let data = TypedData {
87 data: Some(Data::Json(
88 r#"{ "url": "foo", "accessToken": "bar"}"#.to_owned(),
89 )),
90 };
91
92 let info: SignalRConnectionInfo = data.into();
93 assert_eq!(info.url, "foo");
94 assert_eq!(info.access_token, "bar");
95 }
96
97 #[test]
98 fn it_converts_to_body() {
99 let info = SignalRConnectionInfo {
100 url: "foo".to_owned(),
101 access_token: "bar".to_owned(),
102 };
103
104 let body: Body = info.into();
105 assert_eq!(
106 body.as_str().unwrap(),
107 r#"{"url":"foo","accessToken":"bar"}"#
108 );
109 }
110}