tuwunel_service/resolver/
well_known.rs1use tuwunel_core::{Result, debug, debug_error, debug_info, debug_warn, implement, trace};
2
3use super::DestString;
4use crate::client::read_response_capped;
5
6#[implement(super::Service)]
7#[tracing::instrument(
8 name = "well-known",
9 level = "debug",
10 ret(level = "debug"),
11 skip(self)
12)]
13pub(super) async fn request_well_known(&self, dest: &str) -> Result<Option<DestString>> {
14 trace!("Requesting well known for {dest}");
15 let response = self
16 .services
17 .client
18 .well_known
19 .get(format!("https://{dest}/.well-known/matrix/server"))
20 .send()
21 .await;
22
23 trace!("response: {response:?}");
24 if let Err(e) = &response {
25 debug!("error: {e:?}");
26 return Ok(None);
27 }
28
29 let response = response?;
30 if !response.status().is_success() {
31 debug!("response not 2XX");
32 return Ok(None);
33 }
34
35 let Ok(body) = read_response_capped(response, 12288).await else {
36 debug_warn!("response unreadable or exceeds size limit");
37 return Ok(None);
38 };
39
40 let text = String::from_utf8_lossy(&body);
41 trace!("response text: {text:?}");
42
43 let body: serde_json::Value = serde_json::from_str(&text).unwrap_or_default();
44
45 let m_server = body
46 .get("m.server")
47 .unwrap_or(&serde_json::Value::Null)
48 .as_str()
49 .unwrap_or_default();
50
51 if ruma::identifiers_validation::server_name::validate(m_server).is_err() {
52 debug_error!("response content missing or invalid");
53 return Ok(None);
54 }
55
56 debug_info!("{dest:?} found at {m_server:?}");
57 Ok(Some(m_server.into()))
58}