ruma_federation_api/authenticated_media/
get_content.rs

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