feat(media): Remove legacy unauthenticated media support

This commit is contained in:
Erwan Leboucher authored and Ellis Git committed 2026-11-13 21:24:34 +00:00
1 parent 77e8a6b41b
commit 7afe5885e9
9 files changed
+19 -710

No files matched your search

@@ -0,0 +1 @@
Remove support for legacy, unauthenticated media, including the `allow_legacy_media` and `freeze_legacy_media` options.
-1
View File
@@ -31,7 +31,6 @@ rocksdb_log_level = "info"
rocksdb_max_log_files = 1
rocksdb_recovery_mode = 0
rocksdb_paranoid_file_checks = true
allow_legacy_media = true
startup_netburst = true
startup_netburst_keep = -1
allow_invalid_tls_certificates_yes_i_know_what_the_fuck_i_am_doing_with_this_and_i_know_this_is_insecure = true
-23
View File
@@ -1733,29 +1733,6 @@
# env: CONTINUWUITY_BROTLI_COMPRESSION
#brotli_compression = false
# Enable the legacy unauthenticated Matrix media repository endpoints.
# These endpoints consist of:
# - /_matrix/media/*/config
# - /_matrix/media/*/upload
# - /_matrix/media/*/preview_url
# - /_matrix/media/*/download/*
# - /_matrix/media/*/thumbnail/*
#
# The authenticated equivalent endpoints are always enabled.
#
# Defaults to false, as unauthenticated media has been sunsetted.
#
# env: CONTINUWUITY_ALLOW_LEGACY_MEDIA
#allow_legacy_media = false
# If set to true, prevents fetching new legacy remote media.
#
# Legacy media may still be accessible if it was already fetched
# previously and allow_legacy_media is true.
#
# env: CONTINUWUITY_FREEZE_LEGACY_MEDIA
#freeze_legacy_media = true
# Check consistency of the media directory at startup:
# 1. When `media_compat_file_link` is enabled, this check will upgrade
# media when switching back and forth between Conduit and conduwuit.
-398
View File
@@ -1,398 +0,0 @@
#![allow(deprecated)]
use axum::extract::State;
use conduwuit::{
Err, Result, err,
utils::{content_disposition::make_content_disposition, math::ruma_from_usize},
};
use conduwuit_service::media::{CORP_CROSS_ORIGIN, Dim, FileMeta};
use reqwest::Url;
use ruma::{
api::client::media::{
create_content, get_content, get_content_as_filename, get_content_thumbnail,
get_media_config, get_media_preview,
},
assign,
};
use service::media::mxc::Mxc;
use crate::{Ruma, RumaResponse, client::create_content_route};
/// # `GET /_matrix/media/v3/config`
///
/// Returns max upload size.
pub(crate) async fn get_media_config_legacy_route(
State(services): State<crate::State>,
_body: Ruma<get_media_config::v3::Request>,
) -> Result<get_media_config::v3::Response> {
Ok(get_media_config::v3::Response::new(Some(ruma_from_usize(
services.server.config.max_request_size,
))))
}
/// # `GET /_matrix/media/v1/config`
///
/// This is a legacy endpoint ("/v1/") that some very old homeservers and/or
/// clients may call. conduwuit adds these for compatibility purposes.
/// See <https://spec.matrix.org/legacy/legacy/#id27>
///
/// Returns max upload size.
pub(crate) async fn get_media_config_legacy_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_media_config::v3::Request>,
) -> Result<RumaResponse<get_media_config::v3::Response>> {
get_media_config_legacy_route(State(services), body)
.await
.map(RumaResponse)
}
/// # `GET /_matrix/media/v3/preview_url`
///
/// Returns URL preview.
pub(crate) async fn get_media_preview_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_media_preview::v3::Request>,
) -> Result<get_media_preview::v3::Response> {
let sender_user = body.identity.expect_sender_user()?;
let url = &body.url;
let url = Url::parse(&body.url).map_err(|e| {
err!(Request(InvalidParam(
debug_warn!(%sender_user, %url, "Requested URL is not valid: {e}")
)))
})?;
if !services.media.url_preview_allowed(&url) {
return Err!(Request(Forbidden(
debug_warn!(%sender_user, %url, "URL is not allowed to be previewed")
)));
}
let preview = services.media.get_url_preview(&url).await.map_err(|e| {
err!(Request(Unknown(
debug_error!(%sender_user, %url, "Failed to fetch a URL preview: {e}")
)))
})?;
serde_json::value::to_raw_value(&preview)
.map(get_media_preview::v3::Response::from_raw_value)
.map_err(|error| {
err!(Request(Unknown(
debug_error!(%sender_user, %url, "Failed to parse URL preview: {error}")
)))
})
}
/// # `GET /_matrix/media/v1/preview_url`
///
/// This is a legacy endpoint ("/v1/") that some very old homeservers and/or
/// clients may call. conduwuit adds these for compatibility purposes.
/// See <https://spec.matrix.org/legacy/legacy/#id27>
///
/// Returns URL preview.
pub(crate) async fn get_media_preview_legacy_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_media_preview::v3::Request>,
) -> Result<RumaResponse<get_media_preview::v3::Response>> {
get_media_preview_legacy_route(State(services), body)
.await
.map(RumaResponse)
}
/// # `POST /_matrix/media/v1/upload`
///
/// Permanently save media in the server.
///
/// This is a legacy endpoint ("/v1/") that some very old homeservers and/or
/// clients may call. conduwuit adds these for compatibility purposes.
/// See <https://spec.matrix.org/legacy/legacy/#id27>
///
/// - Some metadata will be saved in the database
/// - Media will be saved in the media/ directory
pub(crate) async fn create_content_legacy_route(
State(services): State<crate::State>,
body: Ruma<create_content::v3::Request>,
) -> Result<RumaResponse<create_content::v3::Response>> {
create_content_route(State(services), body)
.await
.map(RumaResponse)
}
/// # `GET /_matrix/media/v3/download/{serverName}/{mediaId}`
///
/// Load media from our server or over federation.
///
/// - Only allows federation if `allow_remote` is true
/// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds
pub(crate) async fn get_content_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_content::v3::Request>,
) -> Result<get_content::v3::Response> {
let mxc = Mxc {
server_name: &body.server_name,
media_id: &body.media_id,
};
match services.media.get(&mxc).await? {
| Some(FileMeta {
content,
content_type,
content_disposition,
}) => {
let content_disposition = make_content_disposition(
content_disposition.as_ref(),
content_type.as_deref(),
None,
);
Ok(assign!(
get_content::v3::Response::new(
content.expect("entire file contents"),
content_type.unwrap_or_default(),
content_disposition,
),
{
cross_origin_resource_policy: Some(CORP_CROSS_ORIGIN.into()),
}
))
},
| _ =>
if !services.globals.server_is_ours(&body.server_name) && body.allow_remote {
let response = services
.media
.fetch_remote_content_legacy(&mxc, body.allow_redirect, body.timeout_ms)
.await
.map_err(|e| {
err!(Request(NotFound(debug_warn!(%mxc, "Fetching media failed: {e:?}"))))
})?;
let content_disposition = make_content_disposition(
response.content_disposition.as_ref(),
response.content_type.as_deref(),
None,
);
Ok(assign!(
get_content::v3::Response::new(
response.file,
response.content_type.unwrap_or_default(),
content_disposition,
),
{
cross_origin_resource_policy: Some(CORP_CROSS_ORIGIN.into()),
}
))
} else {
Err!(Request(NotFound("Media not found.")))
},
}
}
/// # `GET /_matrix/media/v1/download/{serverName}/{mediaId}`
///
/// Load media from our server or over federation.
///
/// This is a legacy endpoint ("/v1/") that some very old homeservers and/or
/// clients may call. conduwuit adds these for compatibility purposes.
/// See <https://spec.matrix.org/legacy/legacy/#id27>
///
/// - Only allows federation if `allow_remote` is true
/// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds
pub(crate) async fn get_content_legacy_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_content::v3::Request>,
) -> Result<RumaResponse<get_content::v3::Response>> {
get_content_legacy_route(State(services), body)
.await
.map(RumaResponse)
}
/// # `GET /_matrix/media/v3/download/{serverName}/{mediaId}/{fileName}`
///
/// Load media from our server or over federation, permitting desired filename.
///
/// - Only allows federation if `allow_remote` is true
/// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds
pub(crate) async fn get_content_as_filename_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_content_as_filename::v3::Request>,
) -> Result<get_content_as_filename::v3::Response> {
let mxc = Mxc {
server_name: &body.server_name,
media_id: &body.media_id,
};
match services.media.get(&mxc).await? {
| Some(FileMeta {
content,
content_type,
content_disposition,
}) => {
let content_disposition = make_content_disposition(
content_disposition.as_ref(),
content_type.as_deref(),
Some(&body.filename),
);
Ok(assign!(get_content_as_filename::v3::Response::new(
content.expect("entire file contents"),
content_type.unwrap_or_default(),
content_disposition,
),
{
cross_origin_resource_policy: Some(CORP_CROSS_ORIGIN.into()),
}
))
},
| _ =>
if !services.globals.server_is_ours(&body.server_name) && body.allow_remote {
let response = services
.media
.fetch_remote_content_legacy(&mxc, body.allow_redirect, body.timeout_ms)
.await
.map_err(|e| {
err!(Request(NotFound(debug_warn!(%mxc, "Fetching media failed: {e:?}"))))
})?;
let content_disposition = make_content_disposition(
response.content_disposition.as_ref(),
response.content_type.as_deref(),
None,
);
Ok(assign!(
get_content_as_filename::v3::Response::new(
response.file,
response.content_type.unwrap_or_default(),
content_disposition,
),
{
cross_origin_resource_policy: Some(CORP_CROSS_ORIGIN.into()),
}
))
} else {
Err!(Request(NotFound("Media not found.")))
},
}
}
/// # `GET /_matrix/media/v1/download/{serverName}/{mediaId}/{fileName}`
///
/// Load media from our server or over federation, permitting desired filename.
///
/// This is a legacy endpoint ("/v1/") that some very old homeservers and/or
/// clients may call. conduwuit adds these for compatibility purposes.
/// See <https://spec.matrix.org/legacy/legacy/#id27>
///
/// - Only allows federation if `allow_remote` is true
/// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds
pub(crate) async fn get_content_as_filename_legacy_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_content_as_filename::v3::Request>,
) -> Result<RumaResponse<get_content_as_filename::v3::Response>> {
get_content_as_filename_legacy_route(State(services), body)
.await
.map(RumaResponse)
}
/// # `GET /_matrix/media/v3/thumbnail/{serverName}/{mediaId}`
///
/// Load media thumbnail from our server or over federation.
///
/// - Only allows federation if `allow_remote` is true
/// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds
pub(crate) async fn get_content_thumbnail_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_content_thumbnail::v3::Request>,
) -> Result<get_content_thumbnail::v3::Response> {
let mxc = Mxc {
server_name: &body.server_name,
media_id: &body.media_id,
};
let dim = Dim::from_ruma(body.width, body.height, body.method.clone())?;
match services.media.get_thumbnail(&mxc, &dim).await? {
| Some(FileMeta {
content,
content_type,
content_disposition,
}) => {
let content_disposition = make_content_disposition(
content_disposition.as_ref(),
content_type.as_deref(),
None,
);
Ok(assign!(
get_content_thumbnail::v3::Response::new(
content.expect("entire file contents"),
content_type.unwrap_or_default(),
content_disposition,
),
{
cross_origin_resource_policy: Some(CORP_CROSS_ORIGIN.to_owned()),
}
))
},
| _ =>
if !services.globals.server_is_ours(&body.server_name) && body.allow_remote {
let response = services
.media
.fetch_remote_thumbnail_legacy(&body)
.await
.map_err(|e| {
err!(Request(NotFound(debug_warn!(%mxc, "Fetching media failed: {e:?}"))))
})?;
let content_disposition = make_content_disposition(
response.content_disposition.as_ref(),
response.content_type.as_deref(),
None,
);
Ok(assign!(
get_content_thumbnail::v3::Response::new(
response.file,
response.content_type.unwrap_or_default(),
content_disposition,
),
{
cross_origin_resource_policy: Some(CORP_CROSS_ORIGIN.to_owned()),
}
))
} else {
Err!(Request(NotFound("Media not found.")))
},
}
}
/// # `GET /_matrix/media/v1/thumbnail/{serverName}/{mediaId}`
///
/// Load media thumbnail from our server or over federation.
///
/// This is a legacy endpoint ("/v1/") that some very old homeservers and/or
/// clients may call. conduwuit adds these for compatibility purposes.
/// See <https://spec.matrix.org/legacy/legacy/#id27>
///
/// - Only allows federation if `allow_remote` is true
/// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds
pub(crate) async fn get_content_thumbnail_legacy_legacy_route(
State(services): State<crate::State>,
body: Ruma<get_content_thumbnail::v3::Request>,
) -> Result<RumaResponse<get_content_thumbnail::v3::Response>> {
get_content_thumbnail_legacy_route(State(services), body)
.await
.map(RumaResponse)
}
-2
View File
@@ -12,7 +12,6 @@ pub(super) mod directory;
pub(super) mod filter;
pub(super) mod keys;
pub(super) mod media;
pub(super) mod media_legacy;
pub(super) mod membership;
pub(super) mod message;
pub(super) mod mutual_rooms;
@@ -57,7 +56,6 @@ pub(super) use directory::*;
pub(super) use filter::*;
pub(super) use keys::*;
pub(super) use media::*;
pub(super) use media_legacy::*;
pub(super) use membership::*;
pub use membership::{leave_all_rooms, leave_room, remote_leave_room};
pub(super) use message::*;
+11 -40
View File
@@ -8,7 +8,7 @@ use std::str::FromStr;
use axum::{
Router,
response::{IntoResponse, Redirect},
routing::{any, get, post},
routing::{any, get},
};
use conduwuit::err;
pub(super) use conduwuit_service::state::State;
@@ -247,45 +247,16 @@ pub fn build(router: Router<State>, state: State) -> Router<State> {
// and other functionality will continue to work
router = router.ruma_route(&server::get_openid_userinfo_route);
if config.allow_legacy_media {
router = router
.ruma_route(&client::get_media_config_legacy_route)
.ruma_route(&client::get_media_preview_legacy_route)
.ruma_route(&client::get_content_legacy_route)
.ruma_route(&client::get_content_as_filename_legacy_route)
.ruma_route(&client::get_content_thumbnail_legacy_route)
.route("/_matrix/media/v1/config", get(client::get_media_config_legacy_legacy_route))
.route("/_matrix/media/v1/upload", post(client::create_content_legacy_route))
.route(
"/_matrix/media/v1/preview_url",
get(client::get_media_preview_legacy_legacy_route),
)
.route(
"/_matrix/media/v1/download/{server_name}/{media_id}",
get(client::get_content_legacy_legacy_route),
)
.route(
"/_matrix/media/v1/download/{server_name}/{media_id}/{file_name}",
get(client::get_content_as_filename_legacy_legacy_route),
)
.route(
"/_matrix/media/v1/thumbnail/{server_name}/{media_id}",
get(client::get_content_thumbnail_legacy_legacy_route),
);
} else {
router = router
.route("/_matrix/media/v1/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/v3/config", any(legacy_media_disabled))
.route("/_matrix/media/v3/download/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/v3/thumbnail/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/v3/preview_url", any(redirect_legacy_preview))
.route("/_matrix/media/r0/config", any(legacy_media_disabled))
.route("/_matrix/media/r0/download/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/r0/thumbnail/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/r0/preview_url", any(redirect_legacy_preview));
}
router
.route("/_matrix/media/v1/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/v3/config", any(legacy_media_disabled))
.route("/_matrix/media/v3/download/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/v3/thumbnail/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/v3/preview_url", any(redirect_legacy_preview))
.route("/_matrix/media/r0/config", any(legacy_media_disabled))
.route("/_matrix/media/r0/download/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/r0/thumbnail/{*path}", any(legacy_media_disabled))
.route("/_matrix/media/r0/preview_url", any(redirect_legacy_preview))
}
async fn redirect_legacy_preview(uri: Uri) -> impl IntoResponse {
@@ -306,7 +277,7 @@ async fn redirect_legacy_preview(uri: Uri) -> impl IntoResponse {
}
async fn legacy_media_disabled() -> impl IntoResponse {
err!(Request(Forbidden("Unauthenticated media is disabled.")))
err!(Request(NotFound("Unauthenticated media is disabled.")))
}
async fn federation_disabled() -> impl IntoResponse {
-25
View File
@@ -1847,31 +1847,6 @@ pub struct Config {
#[serde(default)]
pub brotli_compression: bool,
/// Enable the legacy unauthenticated Matrix media repository endpoints.
/// These endpoints consist of:
/// - /_matrix/media/*/config
/// - /_matrix/media/*/upload
/// - /_matrix/media/*/preview_url
/// - /_matrix/media/*/download/*
/// - /_matrix/media/*/thumbnail/*
///
/// The authenticated equivalent endpoints are always enabled.
///
/// Defaults to false, as unauthenticated media has been sunsetted.
///
/// default: false
#[serde(default)]
pub allow_legacy_media: bool,
/// If set to true, prevents fetching new legacy remote media.
///
/// Legacy media may still be accessible if it was already fetched
/// previously and allow_legacy_media is true.
///
/// default: true
#[serde(default = "true_fn")]
pub freeze_legacy_media: bool,
/// Check consistency of the media directory at startup:
/// 1. When `media_compat_file_link` is enabled, this check will upgrade
/// media when switching back and forth between Conduit and conduwuit.
+5 -197
View File
@@ -1,7 +1,7 @@
use std::{fmt::Debug, time::Duration};
use conduwuit::{
Err, Error, Result, debug_warn, err,
Err, Result, debug_warn, err,
utils::{content_disposition::make_content_disposition, response::LimitReadExt},
};
use http::header::{CONTENT_DISPOSITION, CONTENT_TYPE, HeaderValue};
@@ -9,9 +9,6 @@ use ruma::{
ServerName, UserId,
api::{
OutgoingRequest,
auth_scheme::NoAccessToken,
client::media,
error::ErrorKind::{NotFound, Unrecognized},
federation::{
self,
authenticated_media::{Content, FileOrLocation},
@@ -35,17 +32,8 @@ impl super::Service {
) -> Result<FileMeta> {
self.check_fetch_authorized(mxc)?;
let result = self
.fetch_thumbnail_authenticated(mxc, user, server, timeout_ms, dim)
.await;
if let Err(Error::Request(NotFound, ..)) = &result {
return self
.fetch_thumbnail_unauthenticated(mxc, user, server, timeout_ms, dim)
.await;
}
result
self.fetch_thumbnail_authenticated(mxc, user, server, timeout_ms, dim)
.await
}
pub async fn fetch_remote_content(
@@ -57,8 +45,7 @@ impl super::Service {
) -> Result<FileMeta> {
self.check_fetch_authorized(mxc)?;
let result = self
.fetch_content_authenticated(mxc, user, server, timeout_ms)
self.fetch_content_authenticated(mxc, user, server, timeout_ms)
.await
.inspect_err(|error| {
debug_warn!(
@@ -68,15 +55,7 @@ impl super::Service {
?error,
"Authenticated fetch of remote content failed"
);
});
if let Err(Error::Request(Unrecognized, ..)) = &result {
return self
.fetch_content_unauthenticated(mxc, user, server, timeout_ms)
.await;
}
result
})
}
async fn fetch_thumbnail_authenticated(
@@ -127,66 +106,6 @@ impl super::Service {
}
}
#[allow(deprecated)]
async fn fetch_thumbnail_unauthenticated(
&self,
mxc: &Mxc<'_>,
user: Option<&UserId>,
server: Option<&ServerName>,
timeout_ms: Duration,
dim: &Dim,
) -> Result<FileMeta> {
use media::get_content_thumbnail::v3::{Request, Response};
let mut request = Request::new(
mxc.media_id.into(),
mxc.server_name.into(),
dim.width.into(),
dim.height.into(),
);
request.allow_redirect = true;
request.allow_remote = true;
request.animated = Some(true);
request.method = Some(dim.method.clone());
request.timeout_ms = timeout_ms;
let Response {
file, content_type, content_disposition, ..
} = self
.federation_request_legacy_media(mxc, server, request)
.await?;
let content = Content::new(file, content_type.unwrap(), content_disposition.unwrap());
self.handle_thumbnail_file(mxc, user, dim, content).await
}
#[allow(deprecated)]
async fn fetch_content_unauthenticated(
&self,
mxc: &Mxc<'_>,
user: Option<&UserId>,
server: Option<&ServerName>,
timeout_ms: Duration,
) -> Result<FileMeta> {
use media::get_content::v3::{Request, Response};
let mut request = Request::new(mxc.media_id.into(), mxc.server_name.into());
request.allow_remote = true;
request.allow_redirect = true;
request.timeout_ms = timeout_ms;
let Response {
file, content_type, content_disposition, ..
} = self
.federation_request_legacy_media(mxc, server, request)
.await?;
let content = Content::new(file, content_type.unwrap(), content_disposition.unwrap());
self.handle_content_file(mxc, user, content).await
}
async fn handle_thumbnail_file(
&self,
mxc: &Mxc<'_>,
@@ -319,108 +238,6 @@ impl super::Service {
.await
}
async fn federation_request_legacy_media<'i, Request>(
&self,
mxc: &Mxc<'_>,
server: Option<&ServerName>,
request: Request,
) -> Result<Request::IncomingResponse>
where
Request: OutgoingRequest<
Authentication = NoAccessToken,
PathBuilder: PathBuilder<Input<'i>: FederationPathBuilderInput>,
> + Debug
+ Send,
{
self.services
.sending
.send_legacy_media_request(server.unwrap_or(mxc.server_name), request)
.await
}
#[allow(deprecated)]
pub async fn fetch_remote_thumbnail_legacy(
&self,
body: &media::get_content_thumbnail::v3::Request,
) -> Result<media::get_content_thumbnail::v3::Response> {
let mxc = Mxc {
server_name: &body.server_name,
media_id: &body.media_id,
};
let mut request = media::get_content_thumbnail::v3::Request::new(
body.media_id.clone(),
body.server_name.clone(),
body.width,
body.height,
);
request.method.clone_from(&body.method);
request.allow_remote = body.allow_remote;
request.allow_redirect = body.allow_redirect;
request.animated = body.animated;
request.timeout_ms = body.timeout_ms;
self.check_legacy_freeze()?;
self.check_fetch_authorized(&mxc)?;
let response = self
.services
.sending
.send_legacy_media_request(mxc.server_name, request)
.await?;
let dim = Dim::from_ruma(body.width, body.height, body.method.clone())?;
self.upload_thumbnail(
&mxc,
None,
None,
response.content_type.as_deref(),
&dim,
&response.file,
)
.await?;
Ok(response)
}
#[allow(deprecated)]
pub async fn fetch_remote_content_legacy(
&self,
mxc: &Mxc<'_>,
allow_redirect: bool,
timeout_ms: Duration,
) -> Result<media::get_content::v3::Response, Error> {
let mut request =
media::get_content::v3::Request::new(mxc.media_id.into(), mxc.server_name.into());
request.allow_remote = true;
request.allow_redirect = allow_redirect;
request.timeout_ms = timeout_ms;
self.check_legacy_freeze()?;
self.check_fetch_authorized(mxc)?;
let response = self
.services
.sending
.send_legacy_media_request(mxc.server_name, request)
.await?;
let content_disposition = make_content_disposition(
response.content_disposition.as_ref(),
response.content_type.as_deref(),
None,
);
self.create(
mxc,
None,
Some(&content_disposition),
response.content_type.as_deref(),
&response.file,
)
.await?;
Ok(response)
}
fn check_fetch_authorized(&self, mxc: &Mxc<'_>) -> Result<()> {
if self
.services
@@ -436,13 +253,4 @@ impl super::Service {
Ok(())
}
fn check_legacy_freeze(&self) -> Result<()> {
self.services
.server
.config
.freeze_legacy_media
.then_some(())
.ok_or(err!(Request(NotFound("Remote media is frozen."))))
}
}
+2 -24
View File
@@ -23,10 +23,8 @@ use futures::{FutureExt, Stream, StreamExt};
use ruma::{
OwnedServerName, RoomId, ServerName, UserId,
api::{
OutgoingRequest,
auth_scheme::{NoAccessToken, NoAuthentication, SendAccessToken},
federation::authentication::ServerSignatures,
path_builder::PathBuilder,
OutgoingRequest, auth_scheme::NoAuthentication,
federation::authentication::ServerSignatures, path_builder::PathBuilder,
},
};
use tokio::{task, task::JoinSet};
@@ -420,26 +418,6 @@ impl Service {
.await
}
/// Send an unauthenticated federation request with no X-Matrix header.
#[inline]
pub async fn send_legacy_media_request<'i, T>(
&self,
dest: &ServerName,
request: T,
) -> Result<T::IncomingResponse>
where
T: OutgoingRequest<
Authentication = NoAccessToken,
PathBuilder: PathBuilder<Input<'i>: FederationPathBuilderInput>,
> + Debug
+ Send,
{
self.services
.federation
.execute_on(&self.services.client.federation, dest, request, SendAccessToken::None)
.await
}
/// Clean up queued sending event data
///
/// Used after we remove an appservice registration or a user deletes a push