Skip to main content

tuwunel_api/client/appservice/
ping.rs

1use axum::extract::State;
2use ruma::api::{
3	appservice::ping::send_ping::v1::Request as SendPing, client::appservice::request_ping,
4};
5use tuwunel_core::{Err, Result, err};
6
7use crate::Ruma;
8
9/// # `POST /_matrix/client/v1/appservice/{appserviceId}/ping`
10///
11/// Ask the homeserver to ping the application service to ensure the connection
12/// works.
13pub(crate) async fn appservice_ping(
14	State(services): State<crate::State>,
15	body: Ruma<request_ping::v1::Request>,
16) -> Result<request_ping::v1::Response> {
17	let appservice_info = body.appservice_info.as_ref().ok_or_else(|| {
18		err!(Request(Forbidden("This endpoint can only be called by appservices.")))
19	})?;
20
21	if body.appservice_id != appservice_info.registration.id {
22		return Err!(Request(Forbidden(
23			"Appservices can only ping themselves (wrong appservice ID)."
24		)));
25	}
26
27	if appservice_info.registration.url.is_none()
28		|| appservice_info
29			.registration
30			.url
31			.as_ref()
32			.is_some_and(|url| url.is_empty() || url == "null")
33	{
34		return Err!(Request(UrlNotSet(
35			"Appservice does not have a URL set, there is nothing to ping."
36		)));
37	}
38
39	let timer = tokio::time::Instant::now();
40
41	services
42		.appservice
43		.ping(appservice_info.registration.clone(), SendPing {
44			transaction_id: body.transaction_id.clone(),
45		})
46		.await?;
47
48	Ok(request_ping::v1::Response { duration: timer.elapsed() })
49}