Skip to content

Commit e563e4b

Browse files
authored
Fix content length on federation /thumbnail responses (#17532)
1 parent f4032d3 commit e563e4b

File tree

4 files changed

+41
-20
lines changed

4 files changed

+41
-20
lines changed

changelog.d/17532.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix content-length on federation /thumbnail responses.

synapse/media/_base.py

+11-11
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@
6060

6161
if TYPE_CHECKING:
6262
from synapse.server import HomeServer
63-
from synapse.storage.databases.main.media_repository import LocalMedia
64-
6563

6664
logger = logging.getLogger(__name__)
6765

@@ -290,7 +288,9 @@ async def respond_with_multipart_responder(
290288
clock: Clock,
291289
request: SynapseRequest,
292290
responder: "Optional[Responder]",
293-
media_info: "LocalMedia",
291+
media_type: str,
292+
media_length: Optional[int],
293+
upload_name: Optional[str],
294294
) -> None:
295295
"""
296296
Responds to requests originating from the federation media `/download` endpoint by
@@ -314,24 +314,24 @@ async def respond_with_multipart_responder(
314314
)
315315
return
316316

317-
if media_info.media_type.lower().split(";", 1)[0] in INLINE_CONTENT_TYPES:
317+
if media_type.lower().split(";", 1)[0] in INLINE_CONTENT_TYPES:
318318
disposition = "inline"
319319
else:
320320
disposition = "attachment"
321321

322322
def _quote(x: str) -> str:
323323
return urllib.parse.quote(x.encode("utf-8"))
324324

325-
if media_info.upload_name:
326-
if _can_encode_filename_as_token(media_info.upload_name):
325+
if upload_name:
326+
if _can_encode_filename_as_token(upload_name):
327327
disposition = "%s; filename=%s" % (
328328
disposition,
329-
media_info.upload_name,
329+
upload_name,
330330
)
331331
else:
332332
disposition = "%s; filename*=utf-8''%s" % (
333333
disposition,
334-
_quote(media_info.upload_name),
334+
_quote(upload_name),
335335
)
336336

337337
from synapse.media.media_storage import MultipartFileConsumer
@@ -341,14 +341,14 @@ def _quote(x: str) -> str:
341341
multipart_consumer = MultipartFileConsumer(
342342
clock,
343343
request,
344-
media_info.media_type,
344+
media_type,
345345
{},
346346
disposition,
347-
media_info.media_length,
347+
media_length,
348348
)
349349

350350
logger.debug("Responding to media request with responder %s", responder)
351-
if media_info.media_length is not None:
351+
if media_length is not None:
352352
content_length = multipart_consumer.content_length()
353353
assert content_length is not None
354354
request.setHeader(b"Content-Length", b"%d" % (content_length,))

synapse/media/media_repository.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ async def get_local_media(
471471
responder = await self.media_storage.fetch_media(file_info)
472472
if federation:
473473
await respond_with_multipart_responder(
474-
self.clock, request, responder, media_info
474+
self.clock, request, responder, media_type, media_length, upload_name
475475
)
476476
else:
477477
await respond_with_responder(
@@ -1008,7 +1008,7 @@ async def generate_local_exact_thumbnail(
10081008
t_method: str,
10091009
t_type: str,
10101010
url_cache: bool,
1011-
) -> Optional[str]:
1011+
) -> Optional[Tuple[str, FileInfo]]:
10121012
input_path = await self.media_storage.ensure_media_is_in_local_cache(
10131013
FileInfo(None, media_id, url_cache=url_cache)
10141014
)
@@ -1070,7 +1070,7 @@ async def generate_local_exact_thumbnail(
10701070
t_len,
10711071
)
10721072

1073-
return output_path
1073+
return output_path, file_info
10741074

10751075
# Could not generate thumbnail.
10761076
return None

synapse/media/thumbnailer.py

+26-6
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,12 @@ async def select_or_generate_local_thumbnail(
348348
if responder:
349349
if for_federation:
350350
await respond_with_multipart_responder(
351-
self.hs.get_clock(), request, responder, media_info
351+
self.hs.get_clock(),
352+
request,
353+
responder,
354+
info.type,
355+
info.length,
356+
None,
352357
)
353358
return
354359
else:
@@ -360,7 +365,7 @@ async def select_or_generate_local_thumbnail(
360365
logger.debug("We don't have a thumbnail of that size. Generating")
361366

362367
# Okay, so we generate one.
363-
file_path = await self.media_repo.generate_local_exact_thumbnail(
368+
thumbnail_result = await self.media_repo.generate_local_exact_thumbnail(
364369
media_id,
365370
desired_width,
366371
desired_height,
@@ -369,13 +374,18 @@ async def select_or_generate_local_thumbnail(
369374
url_cache=bool(media_info.url_cache),
370375
)
371376

372-
if file_path:
377+
if thumbnail_result:
378+
file_path, file_info = thumbnail_result
379+
assert file_info.thumbnail is not None
380+
373381
if for_federation:
374382
await respond_with_multipart_responder(
375383
self.hs.get_clock(),
376384
request,
377385
FileResponder(self.hs, open(file_path, "rb")),
378-
media_info,
386+
file_info.thumbnail.type,
387+
file_info.thumbnail.length,
388+
None,
379389
)
380390
else:
381391
await respond_with_file(self.hs, request, desired_type, file_path)
@@ -580,7 +590,12 @@ async def _select_and_respond_with_thumbnail(
580590
if for_federation:
581591
assert media_info is not None
582592
await respond_with_multipart_responder(
583-
self.hs.get_clock(), request, responder, media_info
593+
self.hs.get_clock(),
594+
request,
595+
responder,
596+
file_info.thumbnail.type,
597+
file_info.thumbnail.length,
598+
None,
584599
)
585600
return
586601
else:
@@ -634,7 +649,12 @@ async def _select_and_respond_with_thumbnail(
634649
if for_federation:
635650
assert media_info is not None
636651
await respond_with_multipart_responder(
637-
self.hs.get_clock(), request, responder, media_info
652+
self.hs.get_clock(),
653+
request,
654+
responder,
655+
file_info.thumbnail.type,
656+
file_info.thumbnail.length,
657+
None,
638658
)
639659
else:
640660
await respond_with_responder(

0 commit comments

Comments
 (0)