Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use max_upload_size as the limit when following the Location header #17543

Merged
merged 8 commits into from
Aug 29, 2024
68 changes: 68 additions & 0 deletions tests/http/test_matrixfederationclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# [This file includes modifications made by New Vector Limited]
#
#
import io
from typing import Any, Dict, Generator
from unittest.mock import ANY, Mock, create_autospec

Expand All @@ -32,7 +33,9 @@
from twisted.web.http_headers import Headers

from synapse.api.errors import HttpResponseException, RequestSendFailed
from synapse.api.ratelimiting import Ratelimiter
from synapse.config._base import ConfigError
from synapse.config.ratelimiting import RatelimitSettings
from synapse.http.matrixfederationclient import (
ByteParser,
MatrixFederationHttpClient,
Expand Down Expand Up @@ -337,6 +340,71 @@ def test_client_gets_headers(self) -> None:
r = self.successResultOf(d)
self.assertEqual(r.code, 200)

def test_authed_media_redirect_response(self) -> None:
"""
Validate that, when following a `Location` redirect, the
maximum size is _not_ set to the initial response `Content-Length` and
the media file can be downloaded.
"""
limiter = Ratelimiter(
store=self.hs.get_datastores().main,
clock=self.clock,
cfg=RatelimitSettings(key="", per_second=0.17, burst_count=1048576),
)

output_stream = io.BytesIO()

d = defer.ensureDeferred(
self.cl.federation_get_file(
"testserv:8008", "path", output_stream, limiter, "127.0.0.1", 10000
)
)

self.pump()

conn = Mock()
clients = self.reactor.tcpClients
client = clients[0][2].buildProtocol(None)
client.makeConnection(conn)

# Deferred does not have a result
self.assertNoResult(d)

redirect_data = b"\r\n\r\n--6067d4698f8d40a0a794ea7d7379d53a\r\nContent-Type: application/json\r\n\r\n{}\r\n--6067d4698f8d40a0a794ea7d7379d53a\r\nLocation: http://testserv:8008/ab/c1/2345.txt\r\n\r\n--6067d4698f8d40a0a794ea7d7379d53a--\r\n\r\n"
client.dataReceived(
b"HTTP/1.1 200 OK\r\n"
b"Server: Fake\r\n"
b"Content-Length: %i\r\n"
b"Content-Type: multipart/mixed; boundary=6067d4698f8d40a0a794ea7d7379d53a\r\n\r\n"
% (len(redirect_data))
)
client.dataReceived(redirect_data)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea why this works, but it works, though.


# Still no result, not followed the redirect yet
self.assertNoResult(d)

# Now send the response returned by the server at `Location`
conn = Mock()
clients = self.reactor.tcpClients
S7evinK marked this conversation as resolved.
Show resolved Hide resolved
client = clients[1][2].buildProtocol(None)
client.makeConnection(conn)

# make sure the length is longer than the initial response
data = b"Hello world!" * 30
client.dataReceived(
b"HTTP/1.1 200 OK\r\n"
b"Server: Fake\r\n"
b"Content-Length: %i\r\n"
b"Content-Type: text/plain\r\n"
b"\r\n"
b"%s\r\n"
b"\r\n" % (len(data), data)
)

# We should get a successful response
length, _, _ = self.successResultOf(d)
self.assertEqual(length, len(data))
S7evinK marked this conversation as resolved.
Show resolved Hide resolved

@parameterized.expand(["get_json", "post_json", "delete_json", "put_json"])
def test_timeout_reading_body(self, method_name: str) -> None:
"""
Expand Down
Loading