ruma_client_api/uiaa/
get_uiaa_fallback_page.rs1pub mod v3 {
6 use ruma_common::{
11 api::{auth_scheme::NoAccessToken, request},
12 metadata,
13 };
14
15 use crate::uiaa::AuthType;
16
17 metadata! {
18 method: GET,
19 rate_limited: false,
20 authentication: NoAccessToken,
21 history: {
22 1.0 => "/_matrix/client/r0/auth/{auth_type}/fallback/web",
23 1.1 => "/_matrix/client/v3/auth/{auth_type}/fallback/web",
24 }
25 }
26
27 #[request]
29 pub struct Request {
30 #[ruma_api(path)]
32 pub auth_type: AuthType,
33
34 #[ruma_api(query)]
36 pub session: String,
37 }
38
39 impl Request {
40 pub fn new(auth_type: AuthType, session: String) -> Self {
42 Self { auth_type, session }
43 }
44 }
45
46 #[derive(Debug, Clone)]
48 #[allow(clippy::exhaustive_enums)]
49 pub enum Response {
50 Redirect(Redirect),
52
53 Html(HtmlPage),
55 }
56
57 #[derive(Debug, Clone)]
59 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
60 pub struct Redirect {
61 pub url: String,
63 }
64
65 #[derive(Debug, Clone)]
67 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
68 pub struct HtmlPage {
69 pub body: Vec<u8>,
71 }
72
73 impl Response {
74 pub fn html(body: Vec<u8>) -> Self {
76 Self::Html(HtmlPage { body })
77 }
78
79 pub fn redirect(url: String) -> Self {
81 Self::Redirect(Redirect { url })
82 }
83 }
84
85 #[cfg(feature = "server")]
86 impl ruma_common::api::OutgoingResponse for Response {
87 fn try_into_http_response<T: Default + bytes::BufMut>(
88 self,
89 ) -> Result<http::Response<T>, ruma_common::api::error::IntoHttpError> {
90 match self {
91 Response::Redirect(Redirect { url }) => Ok(http::Response::builder()
92 .status(http::StatusCode::FOUND)
93 .header(http::header::LOCATION, url)
94 .body(T::default())?),
95 Response::Html(HtmlPage { body }) => Ok(http::Response::builder()
96 .status(http::StatusCode::OK)
97 .header(http::header::CONTENT_TYPE, "text/html; charset=utf-8")
98 .body(ruma_common::serde::slice_to_buf(&body))?),
99 }
100 }
101 }
102
103 #[cfg(feature = "client")]
104 impl ruma_common::api::IncomingResponse for Response {
105 type EndpointError = ruma_common::api::error::Error;
106
107 fn try_from_http_response_inner(
108 response: http::Response<&[u8]>,
109 ) -> Result<Self, ruma_common::api::error::DeserializationError> {
110 use ruma_common::api::error::HeaderDeserializationError;
111
112 if response.status() == http::StatusCode::FOUND {
113 let Some(location) = response.headers().get(http::header::LOCATION) else {
114 return Err(HeaderDeserializationError::MissingHeader(
115 http::header::LOCATION.to_string(),
116 )
117 .into());
118 };
119
120 let url = location.to_str()?;
121 return Ok(Self::Redirect(Redirect { url: url.to_owned() }));
122 }
123
124 let body = response.into_body().to_owned();
125 Ok(Self::Html(HtmlPage { body }))
126 }
127 }
128
129 #[cfg(all(test, feature = "client"))]
130 mod tests_client {
131 use assert_matches2::assert_let;
132 use http::header::{CONTENT_TYPE, LOCATION};
133 use ruma_common::api::IncomingResponseExt as _;
134
135 use super::Response;
136
137 #[test]
138 fn incoming_redirect() {
139 use super::Redirect;
140
141 let http_response = http::Response::builder()
142 .status(http::StatusCode::FOUND)
143 .header(LOCATION, "http://localhost/redirect")
144 .body(b"".as_slice())
145 .unwrap();
146
147 let response = Response::try_from_http_response(http_response).unwrap();
148 assert_let!(Response::Redirect(Redirect { url }) = response);
149 assert_eq!(url, "http://localhost/redirect");
150 }
151
152 #[test]
153 fn incoming_html() {
154 use super::HtmlPage;
155
156 let http_response = http::Response::builder()
157 .status(http::StatusCode::OK)
158 .header(CONTENT_TYPE, "text/html; charset=utf-8")
159 .body(b"<h1>My Page</h1>".as_slice())
160 .unwrap();
161
162 let response = Response::try_from_http_response(http_response).unwrap();
163 assert_let!(Response::Html(HtmlPage { body }) = response);
164 assert_eq!(body, b"<h1>My Page</h1>");
165 }
166 }
167
168 #[cfg(all(test, feature = "server"))]
169 mod tests_server {
170 use http::header::{CONTENT_TYPE, LOCATION};
171 use ruma_common::api::OutgoingResponse;
172
173 use super::Response;
174
175 #[test]
176 fn outgoing_redirect() {
177 let response = Response::redirect("http://localhost/redirect".to_owned());
178
179 let http_response = response.try_into_http_response::<Vec<u8>>().unwrap();
180
181 assert_eq!(http_response.status(), http::StatusCode::FOUND);
182 assert_eq!(
183 http_response.headers().get(LOCATION).unwrap().to_str().unwrap(),
184 "http://localhost/redirect"
185 );
186 assert!(http_response.into_body().is_empty());
187 }
188
189 #[test]
190 fn outgoing_html() {
191 let response = Response::html(b"<h1>My Page</h1>".to_vec());
192
193 let http_response = response.try_into_http_response::<Vec<u8>>().unwrap();
194
195 assert_eq!(http_response.status(), http::StatusCode::OK);
196 assert_eq!(
197 http_response.headers().get(CONTENT_TYPE).unwrap().to_str().unwrap(),
198 "text/html; charset=utf-8"
199 );
200 assert_eq!(http_response.into_body(), b"<h1>My Page</h1>");
201 }
202 }
203}