client-api: Implement asynchronous uploads (MSC2246)

https://github.com/matrix-org/matrix-spec-proposals/pull/2246
This commit is contained in:
Charlotte 2022-05-28 21:49:05 +01:00 committed by GitHub
parent 62c4d7ab72
commit ddc5279b6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 178 additions and 4 deletions

View File

@ -18,6 +18,7 @@ rustdoc-args = ["--cfg", "docsrs"]
[features] [features]
compat = [] compat = []
unstable-exhaustive-types = [] unstable-exhaustive-types = []
unstable-msc2246 = []
unstable-msc2448 = [] unstable-msc2448 = []
unstable-msc2654 = [] unstable-msc2654 = []
unstable-msc2676 = [] unstable-msc2676 = []

View File

@ -141,6 +141,14 @@ pub enum ErrorKind {
/// M_WEAK_PASSWORD /// M_WEAK_PASSWORD
WeakPassword, WeakPassword,
/// FI.MAU.MSC2246_NOT_YET_UPLOADED
#[cfg(feature = "unstable-msc2246")]
NotYetUploaded,
/// FI.MAU.MSC2246_CANNOT_OVERWRITE_MEDIA
#[cfg(feature = "unstable-msc2246")]
CannotOverwriteMedia,
#[doc(hidden)] #[doc(hidden)]
_Custom { errcode: PrivOwnedStr, extra: Extra }, _Custom { errcode: PrivOwnedStr, extra: Extra },
} }
@ -185,6 +193,10 @@ impl AsRef<str> for ErrorKind {
Self::ResourceLimitExceeded { .. } => "M_RESOURCE_LIMIT_EXCEEDED", Self::ResourceLimitExceeded { .. } => "M_RESOURCE_LIMIT_EXCEEDED",
Self::CannotLeaveServerNoticeRoom => "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM", Self::CannotLeaveServerNoticeRoom => "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM",
Self::WeakPassword => "M_WEAK_PASSWORD", Self::WeakPassword => "M_WEAK_PASSWORD",
#[cfg(feature = "unstable-msc2246")]
Self::NotYetUploaded => "FI.MAU.MSC2246_NOT_YET_UPLOADED",
#[cfg(feature = "unstable-msc2246")]
Self::CannotOverwriteMedia => "FI.MAU.MSC2246_CANNOT_OVERWRITE_MEDIA",
Self::_Custom { errcode, .. } => &errcode.0, Self::_Custom { errcode, .. } => &errcode.0,
} }
} }

View File

@ -206,6 +206,10 @@ impl<'de> Visitor<'de> for ErrorKindVisitor {
}, },
ErrCode::CannotLeaveServerNoticeRoom => ErrorKind::CannotLeaveServerNoticeRoom, ErrCode::CannotLeaveServerNoticeRoom => ErrorKind::CannotLeaveServerNoticeRoom,
ErrCode::WeakPassword => ErrorKind::WeakPassword, ErrCode::WeakPassword => ErrorKind::WeakPassword,
#[cfg(feature = "unstable-msc2246")]
ErrCode::NotYetUploaded => ErrorKind::NotYetUploaded,
#[cfg(feature = "unstable-msc2246")]
ErrCode::CannotOverwriteMedia => ErrorKind::CannotOverwriteMedia,
ErrCode::_Custom(errcode) => ErrorKind::_Custom { errcode, extra }, ErrCode::_Custom(errcode) => ErrorKind::_Custom { errcode, extra },
}) })
} }
@ -247,6 +251,15 @@ enum ErrCode {
ResourceLimitExceeded, ResourceLimitExceeded,
CannotLeaveServerNoticeRoom, CannotLeaveServerNoticeRoom,
WeakPassword, WeakPassword,
#[cfg(feature = "unstable-msc2246")]
#[ruma_enum(rename = "FI.MAU.MSC2246_NOT_YET_UPLOADED", alias = "M_NOT_YET_UPLOADED")]
NotYetUploaded,
#[cfg(feature = "unstable-msc2246")]
#[ruma_enum(
rename = "FI.MAU.MSC2246_CANNOT_OVERWRITE_MEDIA",
alias = "M_CANNOT_OVERWRITE_MEDIA"
)]
CannotOverwriteMedia,
_Custom(PrivOwnedStr), _Custom(PrivOwnedStr),
} }

View File

@ -1,6 +1,10 @@
//! Endpoints for the media repository. //! Endpoints for the media repository.
pub mod create_content; pub mod create_content;
#[cfg(feature = "unstable-msc2246")]
pub mod create_content_async;
#[cfg(feature = "unstable-msc2246")]
pub mod create_mxc_uri;
pub mod get_content; pub mod get_content;
pub mod get_content_as_filename; pub mod get_content_as_filename;
pub mod get_content_thumbnail; pub mod get_content_thumbnail;

View File

@ -0,0 +1,57 @@
//! `POST /_matrix/media/*/upload/{serverName}/{mediaId}`
pub mod unstable {
//! `/unstable/` ([spec])
//!
//! [spec]: https://github.com/tulir/matrix-doc/blob/asynchronous_uploads/proposals/2246-asynchronous-uploads.md
use ruma_common::{api::ruma_api, IdParseError, MxcUri, ServerName};
ruma_api! {
metadata: {
description: "Upload media to an MXC URI that was created with create_mxc_uri.",
method: PUT,
name: "create_content_async",
unstable_path: "/_matrix/media/unstable/fi.mau.msc2246/upload/:server_name/:media_id",
rate_limited: true,
authentication: AccessToken,
}
request: {
/// The media ID from the mxc:// URI (the path component).
#[ruma_api(path)]
pub media_id: &'a str,
/// The server name from the mxc:// URI (the authoritory component).
#[ruma_api(path)]
pub server_name: &'a ServerName,
/// The file contents to upload.
#[ruma_api(raw_body)]
pub file: &'a [u8],
/// The content type of the file being uploaded.
#[ruma_api(header = CONTENT_TYPE)]
pub content_type: Option<&'a str>,
// TODO: How does this and msc2448 (blurhash) interact?
}
response: {}
error: crate::Error
}
impl<'a> Request<'a> {
/// Creates a new `Request` with the given file contents.
pub fn new(media_id: &'a str, server_name: &'a ServerName, file: &'a [u8]) -> Self {
Self { media_id, server_name, file, content_type: None }
}
/// Creates a new `Request` with the given url and file contents.
pub fn from_url(url: &'a MxcUri, file: &'a [u8]) -> Result<Self, IdParseError> {
let (server_name, media_id) = url.parts()?;
Ok(Self::new(media_id, server_name, file))
}
}
}

View File

@ -0,0 +1,40 @@
//! `POST /_matrix/media/*/create`
pub mod unstable {
//! `/unstable/` ([spec])
//!
//! [spec]: https://github.com/tulir/matrix-doc/blob/asynchronous_uploads/proposals/2246-asynchronous-uploads.md
use js_int::UInt;
use ruma_common::{api::ruma_api, OwnedMxcUri};
ruma_api! {
metadata: {
description: "Create an MXC URI without content.",
method: POST,
name: "create_mxc_uri",
unstable_path: "/_matrix/media/unstable/fi.mau.msc2246/create",
rate_limited: true,
authentication: AccessToken,
}
request: {}
response: {
/// The MXC URI for the about to be uploaded content.
pub content_uri: OwnedMxcUri,
/// The time at which the URI will expire if an upload has not been started.
pub unused_expires_at: UInt,
}
error: crate::Error
}
impl Response {
/// Creates a new `Response` with the given MXC URI which expires at a given point in time.
pub fn new(content_uri: OwnedMxcUri, unused_expires_at: UInt) -> Self {
Self { content_uri, unused_expires_at }
}
}
}

View File

@ -5,6 +5,8 @@ pub mod v3 {
//! //!
//! [spec]: https://spec.matrix.org/v1.2/client-server-api/#get_matrixmediav3downloadservernamemediaid //! [spec]: https://spec.matrix.org/v1.2/client-server-api/#get_matrixmediav3downloadservernamemediaid
#[cfg(feature = "unstable-msc2246")]
use js_int::UInt;
use ruma_common::{api::ruma_api, IdParseError, MxcUri, ServerName}; use ruma_common::{api::ruma_api, IdParseError, MxcUri, ServerName};
ruma_api! { ruma_api! {
@ -34,6 +36,21 @@ pub mod v3 {
#[ruma_api(query)] #[ruma_api(query)]
#[serde(default = "ruma_common::serde::default_true", skip_serializing_if = "ruma_common::serde::is_true")] #[serde(default = "ruma_common::serde::default_true", skip_serializing_if = "ruma_common::serde::is_true")]
pub allow_remote: bool, pub allow_remote: bool,
/// How long to wait for the media to be uploaded
///
/// This uses the unstable prefix in
/// [MSC2246](https://github.com/matrix-org/matrix-spec-proposals/pull/2246)
#[ruma_api(query)]
#[cfg(feature = "unstable-msc2246")]
#[serde(
default,
skip_serializing_if = "ruma_common::serde::is_default",
rename = "fi.mau.msc2246.max_stall_ms",
alias = "max_stall_ms"
)]
pub max_stall_ms: Option<UInt>,
} }
response: { response: {
@ -61,14 +78,20 @@ pub mod v3 {
impl<'a> Request<'a> { impl<'a> Request<'a> {
/// Creates a new `Request` with the given media ID and server name. /// Creates a new `Request` with the given media ID and server name.
pub fn new(media_id: &'a str, server_name: &'a ServerName) -> Self { pub fn new(media_id: &'a str, server_name: &'a ServerName) -> Self {
Self { media_id, server_name, allow_remote: true } Self {
media_id,
server_name,
allow_remote: true,
#[cfg(feature = "unstable-msc2246")]
max_stall_ms: None,
}
} }
/// Creates a new `Request` with the given url. /// Creates a new `Request` with the given url.
pub fn from_url(url: &'a MxcUri) -> Result<Self, IdParseError> { pub fn from_url(url: &'a MxcUri) -> Result<Self, IdParseError> {
let (server_name, media_id) = url.parts()?; let (server_name, media_id) = url.parts()?;
Ok(Self { media_id, server_name, allow_remote: true }) Ok(Self::new(media_id, server_name))
} }
} }

View File

@ -54,6 +54,20 @@ pub mod v3 {
#[ruma_api(query)] #[ruma_api(query)]
#[serde(default = "ruma_common::serde::default_true", skip_serializing_if = "ruma_common::serde::is_true")] #[serde(default = "ruma_common::serde::default_true", skip_serializing_if = "ruma_common::serde::is_true")]
pub allow_remote: bool, pub allow_remote: bool,
/// How long to wait for the media to be uploaded
///
/// This uses the unstable prefix in
/// [MSC2246](https://github.com/matrix-org/matrix-spec-proposals/pull/2246)
#[ruma_api(query)]
#[cfg(feature = "unstable-msc2246")]
#[serde(
default,
skip_serializing_if = "ruma_common::serde::is_default",
rename = "fi.mau.msc2246.max_stall_ms",
alias = "max_stall_ms"
)]
pub max_stall_ms: Option<UInt>,
} }
response: { response: {
@ -78,7 +92,16 @@ pub mod v3 {
width: UInt, width: UInt,
height: UInt, height: UInt,
) -> Self { ) -> Self {
Self { media_id, server_name, method: None, width, height, allow_remote: true } Self {
media_id,
server_name,
method: None,
width,
height,
allow_remote: true,
#[cfg(feature = "unstable-msc2246")]
max_stall_ms: None,
}
} }
/// Creates a new `Request` with the given url, desired thumbnail width and /// Creates a new `Request` with the given url, desired thumbnail width and
@ -86,7 +109,7 @@ pub mod v3 {
pub fn from_url(url: &'a MxcUri, width: UInt, height: UInt) -> Result<Self, IdParseError> { pub fn from_url(url: &'a MxcUri, width: UInt, height: UInt) -> Result<Self, IdParseError> {
let (server_name, media_id) = url.parts()?; let (server_name, media_id) = url.parts()?;
Ok(Self { media_id, server_name, method: None, width, height, allow_remote: true }) Ok(Self::new(media_id, server_name, width, height))
} }
} }

View File

@ -118,6 +118,7 @@ unstable-pre-spec = [
"ruma-push-gateway-api/unstable-pre-spec", "ruma-push-gateway-api/unstable-pre-spec",
] ]
unstable-msc1767 = ["ruma-common/unstable-msc1767"] unstable-msc1767 = ["ruma-common/unstable-msc1767"]
unstable-msc2246 = ["ruma-client-api/unstable-msc2246"]
unstable-msc2448 = [ unstable-msc2448 = [
"ruma-client-api/unstable-msc2448", "ruma-client-api/unstable-msc2448",
"ruma-common/unstable-msc2448", "ruma-common/unstable-msc2448",