Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Allow response of /send_join to be larger. #10093

Merged
merged 2 commits into from
May 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/10093.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix HTTP response size limit to allow joining very large rooms over federation.
7 changes: 7 additions & 0 deletions synapse/federation/transport/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@

logger = logging.getLogger(__name__)

# Send join responses can be huge, so we set a separate limit here. The response
# is parsed in a streaming manner, which helps alleviate the issue of memory
# usage a bit.
MAX_RESPONSE_SIZE_SEND_JOIN = 500 * 1024 * 1024


class TransportLayerClient:
"""Sends federation HTTP requests to other servers"""
Expand Down Expand Up @@ -261,6 +266,7 @@ async def send_join_v1(
path=path,
data=content,
parser=SendJoinParser(room_version, v1_api=True),
max_response_size=MAX_RESPONSE_SIZE_SEND_JOIN,
)

return response
Expand All @@ -276,6 +282,7 @@ async def send_join_v2(
path=path,
data=content,
parser=SendJoinParser(room_version, v1_api=False),
max_response_size=MAX_RESPONSE_SIZE_SEND_JOIN,
)

return response
Expand Down
14 changes: 13 additions & 1 deletion synapse/http/matrixfederationclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ async def _handle_response(
response: IResponse,
start_ms: int,
parser: ByteParser[T],
max_response_size: Optional[int] = None,
) -> T:
"""
Reads the body of a response with a timeout and sends it to a parser
Expand All @@ -216,15 +217,20 @@ async def _handle_response(
response: response to the request
start_ms: Timestamp when request was made
parser: The parser for the response
max_response_size: The maximum size to read from the response, if None
uses the default.

Returns:
The parsed response
"""

if max_response_size is None:
max_response_size = MAX_RESPONSE_SIZE

try:
check_content_type_is(response.headers, parser.CONTENT_TYPE)

d = read_body_with_max_size(response, parser, MAX_RESPONSE_SIZE)
d = read_body_with_max_size(response, parser, max_response_size)
d = timeout_deferred(d, timeout=timeout_sec, reactor=reactor)

length = await make_deferred_yieldable(d)
Expand Down Expand Up @@ -735,6 +741,7 @@ async def put_json(
backoff_on_404: bool = False,
try_trailing_slash_on_400: bool = False,
parser: Literal[None] = None,
max_response_size: Optional[int] = None,
) -> Union[JsonDict, list]:
...

Expand All @@ -752,6 +759,7 @@ async def put_json(
backoff_on_404: bool = False,
try_trailing_slash_on_400: bool = False,
parser: Optional[ByteParser[T]] = None,
max_response_size: Optional[int] = None,
) -> T:
...

Expand All @@ -768,6 +776,7 @@ async def put_json(
backoff_on_404: bool = False,
try_trailing_slash_on_400: bool = False,
parser: Optional[ByteParser] = None,
max_response_size: Optional[int] = None,
):
"""Sends the specified json data using PUT

Expand Down Expand Up @@ -803,6 +812,8 @@ async def put_json(
enabled.
parser: The parser to use to decode the response. Defaults to
parsing as JSON.
max_response_size: The maximum size to read from the response, if None
uses the default.

Returns:
Succeeds when we get a 2xx HTTP response. The
Expand Down Expand Up @@ -853,6 +864,7 @@ async def put_json(
response,
start_ms,
parser=parser,
max_response_size=max_response_size,
)

return body
Expand Down