tuwunel_service/appservice/
ping.rs1use bytes::BytesMut;
2use reqwest::Request;
3use ruma::api::{
4 OutgoingRequest,
5 appservice::{Registration, ping::send_ping},
6 auth_scheme::SendAccessToken,
7 error::{BadStatusErrorData, ErrorKind},
8};
9use tuwunel_core::{
10 Error, Result, err, http::StatusCode, implement, utils::string_from_bytes, warn,
11};
12
13use super::request::add_access_token_query;
14use crate::client::read_response_capped;
15
16#[implement(super::Service)]
20pub async fn ping(
21 &self,
22 registration: Registration,
23 request: send_ping::v1::Request,
24) -> Result<()> {
25 let Some(dest) = registration.url else {
26 return Ok(());
27 };
28
29 if dest == *"null" || dest.is_empty() {
30 return Ok(());
31 }
32
33 let hs_token = registration.hs_token.as_str();
34 let mut http_request = request
35 .try_into_http_request::<BytesMut>(&dest, SendAccessToken::IfRequired(hs_token), ())
36 .map_err(|e| {
37 err!(Request(ConnectionFailed(warn!(
38 appservice = %registration.id,
39 %dest,
40 ?e,
41 "Failed to find appservice destination"
42 ))))
43 })?
44 .map(BytesMut::freeze);
45
46 add_access_token_query(&mut http_request, hs_token);
47
48 let reqwest_request = Request::try_from(http_request)?;
49
50 let response = self
51 .services
52 .client
53 .appservice
54 .execute(reqwest_request)
55 .await
56 .map_err(|e| {
57 if e.is_timeout() {
58 err!(Request(ConnectionTimeout(warn!(
59 appservice = %registration.id,
60 %dest,
61 ?e,
62 "Connection to appservice timed out"
63 ))))
64 } else {
65 err!(Request(ConnectionFailed(warn!(
66 appservice = %registration.id,
67 %dest,
68 ?e,
69 "Could not send request to appservice"
70 ))))
71 }
72 })?;
73
74 let status = response.status();
75 if status.is_success() {
76 return Ok(());
77 }
78
79 let limit = self.services.config.max_response_size;
80 let body = read_response_capped(response, limit)
81 .await
82 .ok()
83 .and_then(|body| string_from_bytes(&body).ok());
84
85 warn!(
86 appservice = %registration.id,
87 %status,
88 %dest,
89 "Appservice returned unsuccessful HTTP response to ping"
90 );
91
92 Err(Error::Request(
93 ErrorKind::BadStatus(BadStatusErrorData { status: Some(status), body }),
94 format!("Appservice returned status {status}").into(),
95 StatusCode::BAD_REQUEST,
96 ))
97}