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}