diff --git a/src/client_server/media.rs b/src/client_server/media.rs
index 0a7f4bb5..2e3cf056 100644
--- a/src/client_server/media.rs
+++ b/src/client_server/media.rs
@@ -4,7 +4,10 @@ use crate::{
};
use ruma::api::client::{
error::ErrorKind,
- r0::media::{create_content, get_content, get_content_thumbnail, get_media_config},
+ r0::media::{
+ create_content, get_content, get_content_as_filename, get_content_thumbnail,
+ get_media_config,
+ },
};
use std::convert::TryInto;
@@ -129,6 +132,65 @@ pub async fn get_content_route(
}
}
+/// # `GET /_matrix/media/r0/download/{serverName}/{mediaId}/{fileName}`
+///
+/// Load media from our server or over federation, permitting desired filename.
+///
+/// - Only allows federation if `allow_remote` is true
+#[cfg_attr(
+ feature = "conduit_bin",
+ get("/_matrix/media/r0/download/<_>/<_>/<_>", data = "
")
+)]
+#[tracing::instrument(skip(db, body))]
+pub async fn get_content_as_filename_route(
+ db: DatabaseGuard,
+ body: Ruma>,
+) -> ConduitResult {
+ let mxc = format!("mxc://{}/{}", body.server_name, body.media_id);
+
+ if let Some(FileMeta {
+ content_disposition: _,
+ content_type,
+ file,
+ }) = db.media.get(&db.globals, &mxc).await?
+ {
+ Ok(get_content_as_filename::Response {
+ file,
+ content_type,
+ content_disposition: Some(format!("inline; filename={}", body.filename)),
+ }
+ .into())
+ } else if &*body.server_name != db.globals.server_name() && body.allow_remote {
+ let get_content_response = db
+ .sending
+ .send_federation_request(
+ &db.globals,
+ &body.server_name,
+ get_content_as_filename::Request {
+ allow_remote: false,
+ server_name: &body.server_name,
+ media_id: &body.media_id,
+ filename: &body.filename,
+ },
+ )
+ .await?;
+
+ db.media
+ .create(
+ mxc,
+ &db.globals,
+ &get_content_response.content_disposition.as_deref(),
+ &get_content_response.content_type.as_deref(),
+ &get_content_response.file,
+ )
+ .await?;
+
+ Ok(get_content_response.into())
+ } else {
+ Err(Error::BadRequest(ErrorKind::NotFound, "Media not found."))
+ }
+}
+
/// # `POST /_matrix/media/r0/thumbnail/{serverName}/{mediaId}`
///
/// Load media thumbnail from our server or over federation.
diff --git a/src/main.rs b/src/main.rs
index 56faa3e7..514c2448 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -136,6 +136,7 @@ fn setup_rocket(config: Figment, data: Arc>) -> rocket::Rocket<
client_server::send_event_to_device_route,
client_server::get_media_config_route,
client_server::create_content_route,
+ client_server::get_content_as_filename_route,
client_server::get_content_route,
client_server::get_content_thumbnail_route,
client_server::get_devices_route,