ruma_client_api/state/
get_state_event_for_key.rs1pub mod v3 {
6 use ruma_common::{
11 api::{response, Metadata},
12 metadata,
13 serde::Raw,
14 OwnedRoomId,
15 };
16 use ruma_events::{AnyStateEvent, AnyStateEventContent, StateEventType};
17 use serde_json::value::RawValue as RawJsonValue;
18
19 const METADATA: Metadata = metadata! {
20 method: GET,
21 rate_limited: false,
22 authentication: AccessToken,
23 history: {
24 1.0 => "/_matrix/client/r0/rooms/{room_id}/state/{event_type}/{state_key}",
25 1.1 => "/_matrix/client/v3/rooms/{room_id}/state/{event_type}/{state_key}",
26 }
27 };
28
29 #[derive(Clone, Debug)]
31 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
32 pub struct Request {
33 pub room_id: OwnedRoomId,
35
36 pub event_type: StateEventType,
38
39 pub state_key: String,
41
42 pub format: StateEventFormat,
44 }
45
46 impl Request {
47 pub fn new(room_id: OwnedRoomId, event_type: StateEventType, state_key: String) -> Self {
49 Self { room_id, event_type, state_key, format: StateEventFormat::default() }
50 }
51 }
52
53 #[cfg_attr(feature = "client", derive(serde::Serialize))]
55 #[cfg_attr(feature = "server", derive(serde::Deserialize))]
56 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
57 #[derive(Default, Debug, PartialEq, Clone, Copy)]
58 #[serde(rename_all = "lowercase")]
59 pub enum StateEventFormat {
60 #[default]
64 Content,
65
66 Event,
69 }
70
71 #[response(error = crate::Error)]
77 pub struct Response {
78 #[ruma_api(body)]
80 pub event_or_content: Box<RawJsonValue>,
81 }
82
83 impl From<Raw<AnyStateEvent>> for Response {
84 fn from(value: Raw<AnyStateEvent>) -> Self {
85 Self { event_or_content: value.into_json() }
86 }
87 }
88
89 impl From<Raw<AnyStateEventContent>> for Response {
90 fn from(value: Raw<AnyStateEventContent>) -> Self {
91 Self { event_or_content: value.into_json() }
92 }
93 }
94
95 impl Response {
96 pub fn new(event_or_content: Box<RawJsonValue>) -> Self {
98 Self { event_or_content }
99 }
100
101 pub fn into_event(self) -> Raw<AnyStateEvent> {
106 Raw::from_json(self.event_or_content)
107 }
108
109 pub fn into_content(self) -> Raw<AnyStateEventContent> {
118 Raw::from_json(self.event_or_content)
119 }
120 }
121
122 #[cfg(feature = "client")]
123 impl ruma_common::api::OutgoingRequest for Request {
124 type EndpointError = crate::Error;
125 type IncomingResponse = Response;
126
127 const METADATA: Metadata = METADATA;
128
129 fn try_into_http_request<T: Default + bytes::BufMut>(
130 self,
131 base_url: &str,
132 access_token: ruma_common::api::SendAccessToken<'_>,
133 considering: &'_ ruma_common::api::SupportedVersions,
134 ) -> Result<http::Request<T>, ruma_common::api::error::IntoHttpError> {
135 use http::header;
136
137 let query_string = serde_html_form::to_string(RequestQuery { format: self.format })?;
138
139 http::Request::builder()
140 .method(http::Method::GET)
141 .uri(METADATA.make_endpoint_url(
142 considering,
143 base_url,
144 &[&self.room_id, &self.event_type, &self.state_key],
145 &query_string,
146 )?)
147 .header(header::CONTENT_TYPE, "application/json")
148 .header(
149 header::AUTHORIZATION,
150 format!(
151 "Bearer {}",
152 access_token
153 .get_required_for_endpoint()
154 .ok_or(ruma_common::api::error::IntoHttpError::NeedsAuthentication)?,
155 ),
156 )
157 .body(T::default())
158 .map_err(Into::into)
159 }
160 }
161
162 #[cfg(feature = "server")]
163 impl ruma_common::api::IncomingRequest for Request {
164 type EndpointError = crate::Error;
165 type OutgoingResponse = Response;
166
167 const METADATA: Metadata = METADATA;
168
169 fn try_from_http_request<B, S>(
170 request: http::Request<B>,
171 path_args: &[S],
172 ) -> Result<Self, ruma_common::api::error::FromHttpRequestError>
173 where
174 B: AsRef<[u8]>,
175 S: AsRef<str>,
176 {
177 let (room_id, event_type, state_key): (OwnedRoomId, StateEventType, String) =
180 if path_args.len() == 3 {
181 serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
182 _,
183 serde::de::value::Error,
184 >::new(
185 path_args.iter().map(::std::convert::AsRef::as_ref),
186 ))?
187 } else {
188 let (a, b) =
189 serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
190 _,
191 serde::de::value::Error,
192 >::new(
193 path_args.iter().map(::std::convert::AsRef::as_ref),
194 ))?;
195
196 (a, b, "".into())
197 };
198
199 let RequestQuery { format } =
200 serde_html_form::from_str(request.uri().query().unwrap_or(""))?;
201
202 Ok(Self { room_id, event_type, state_key, format })
203 }
204 }
205
206 #[derive(Debug)]
208 #[cfg_attr(feature = "client", derive(serde::Serialize))]
209 #[cfg_attr(feature = "server", derive(serde::Deserialize))]
210 struct RequestQuery {
211 #[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
213 format: StateEventFormat,
214 }
215}
216
217#[cfg(all(test, feature = "client"))]
218mod tests {
219 use ruma_common::api::IncomingResponse;
220 use ruma_events::room::name::RoomNameEventContent;
221 use serde_json::{json, to_vec as to_json_vec};
222
223 use super::v3::Response;
224
225 #[test]
226 fn deserialize_response() {
227 let body = json!({
228 "name": "Nice room 🙂"
229 });
230 let response = http::Response::new(to_json_vec(&body).unwrap());
231
232 let response = Response::try_from_http_response(response).unwrap();
233 let content =
234 response.into_content().deserialize_as_unchecked::<RoomNameEventContent>().unwrap();
235
236 assert_eq!(&content.name, "Nice room 🙂");
237 }
238}