diff options
Diffstat (limited to 'synapse/federation/transport/server/federation.py')
-rw-r--r-- | synapse/federation/transport/server/federation.py | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/synapse/federation/transport/server/federation.py b/synapse/federation/transport/server/federation.py index ec957768d4..b075a86f68 100644 --- a/synapse/federation/transport/server/federation.py +++ b/synapse/federation/transport/server/federation.py @@ -46,11 +46,13 @@ from synapse.http.servlet import ( parse_boolean_from_args, parse_integer, parse_integer_from_args, + parse_string, parse_string_from_args, parse_strings_from_args, ) from synapse.http.site import SynapseRequest from synapse.media._base import DEFAULT_MAX_TIMEOUT_MS, MAXIMUM_ALLOWED_MAX_TIMEOUT_MS +from synapse.media.thumbnailer import ThumbnailProvider from synapse.types import JsonDict from synapse.util import SYNAPSE_VERSION from synapse.util.ratelimitutils import FederationRateLimiter @@ -826,6 +828,59 @@ class FederationMediaDownloadServlet(BaseFederationServerServlet): ) +class FederationMediaThumbnailServlet(BaseFederationServerServlet): + """ + Implementation of new federation media `/thumbnail` endpoint outlined in MSC3916. Returns + a multipart/mixed response consisting of a JSON object and the requested media + item. This endpoint only returns local media. + """ + + PATH = "/media/thumbnail/(?P<media_id>[^/]*)" + RATELIMIT = True + + def __init__( + self, + hs: "HomeServer", + ratelimiter: FederationRateLimiter, + authenticator: Authenticator, + server_name: str, + ): + super().__init__(hs, authenticator, ratelimiter, server_name) + self.media_repo = self.hs.get_media_repository() + self.dynamic_thumbnails = hs.config.media.dynamic_thumbnails + self.thumbnail_provider = ThumbnailProvider( + hs, self.media_repo, self.media_repo.media_storage + ) + + async def on_GET( + self, + origin: Optional[str], + content: Literal[None], + request: SynapseRequest, + media_id: str, + ) -> None: + + width = parse_integer(request, "width", required=True) + height = parse_integer(request, "height", required=True) + method = parse_string(request, "method", "scale") + # TODO Parse the Accept header to get an prioritised list of thumbnail types. + m_type = "image/png" + max_timeout_ms = parse_integer( + request, "timeout_ms", default=DEFAULT_MAX_TIMEOUT_MS + ) + max_timeout_ms = min(max_timeout_ms, MAXIMUM_ALLOWED_MAX_TIMEOUT_MS) + + if self.dynamic_thumbnails: + await self.thumbnail_provider.select_or_generate_local_thumbnail( + request, media_id, width, height, method, m_type, max_timeout_ms, True + ) + else: + await self.thumbnail_provider.respond_local_thumbnail( + request, media_id, width, height, method, m_type, max_timeout_ms, True + ) + self.media_repo.mark_recently_accessed(None, media_id) + + FEDERATION_SERVLET_CLASSES: Tuple[Type[BaseFederationServlet], ...] = ( FederationSendServlet, FederationEventServlet, @@ -858,4 +913,5 @@ FEDERATION_SERVLET_CLASSES: Tuple[Type[BaseFederationServlet], ...] = ( FederationMakeKnockServlet, FederationAccountStatusServlet, FederationMediaDownloadServlet, + FederationMediaThumbnailServlet, ) |