ruma_federation_api/authenticated_media/get_content/
v1.rs

1//! `/v1/` ([spec])
2//!
3//! [spec]: https://spec.matrix.org/latest/server-server-api/#get_matrixfederationv1mediadownloadmediaid
4
5use std::time::Duration;
6
7use ruma_common::{api::request, metadata};
8
9use crate::{
10    authenticated_media::{ContentMetadata, FileOrLocation},
11    authentication::ServerSignatures,
12};
13
14metadata! {
15    method: GET,
16    rate_limited: true,
17    authentication: ServerSignatures,
18    path: "/_matrix/federation/v1/media/download/{media_id}",
19}
20
21/// Request type for the `get_content` endpoint.
22#[request]
23pub struct Request {
24    /// The media ID from the `mxc://` URI (the path component).
25    #[ruma_api(path)]
26    pub media_id: String,
27
28    /// The maximum duration that the client is willing to wait to start receiving data, in the
29    /// case that the content has not yet been uploaded.
30    ///
31    /// The default value is 20 seconds.
32    #[ruma_api(query)]
33    #[serde(
34        with = "ruma_common::serde::duration::ms",
35        default = "ruma_common::media::default_download_timeout",
36        skip_serializing_if = "ruma_common::media::is_default_download_timeout"
37    )]
38    pub timeout_ms: Duration,
39}
40
41impl Request {
42    /// Creates a new `Request` with the given media ID.
43    pub fn new(media_id: String) -> Self {
44        Self { media_id, timeout_ms: ruma_common::media::default_download_timeout() }
45    }
46}
47
48/// Response type for the `get_content` endpoint.
49#[derive(Debug, Clone)]
50#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
51pub struct Response {
52    /// The metadata of the media.
53    pub metadata: ContentMetadata,
54
55    /// The content of the media.
56    pub content: FileOrLocation,
57}
58
59impl Response {
60    /// Creates a new `Response` with the given metadata and content.
61    pub fn new(metadata: ContentMetadata, content: FileOrLocation) -> Self {
62        Self { metadata, content }
63    }
64}
65
66#[cfg(feature = "client")]
67impl ruma_common::api::IncomingResponse for Response {
68    type EndpointError = ruma_common::api::error::MatrixError;
69
70    fn try_from_http_response<T: AsRef<[u8]>>(
71        http_response: http::Response<T>,
72    ) -> Result<Self, ruma_common::api::error::FromHttpResponseError<Self::EndpointError>> {
73        use ruma_common::api::EndpointError;
74
75        if http_response.status().as_u16() < 400 {
76            let (metadata, content) =
77                crate::authenticated_media::try_from_multipart_mixed_response(http_response)?;
78            Ok(Self { metadata, content })
79        } else {
80            Err(ruma_common::api::error::FromHttpResponseError::Server(
81                ruma_common::api::error::MatrixError::from_http_response(http_response),
82            ))
83        }
84    }
85}
86
87#[cfg(feature = "server")]
88impl ruma_common::api::OutgoingResponse for Response {
89    fn try_into_http_response<T: Default + bytes::BufMut>(
90        self,
91    ) -> Result<http::Response<T>, ruma_common::api::error::IntoHttpError> {
92        crate::authenticated_media::try_into_multipart_mixed_response(&self.metadata, &self.content)
93    }
94}