def test_with_request_context(self): """ Information from the logging context request should be added to the JSON response. """ handler = logging.StreamHandler(self.output) handler.setFormatter(JsonFormatter()) handler.addFilter(LoggingContextFilter()) logger = self.get_logger(handler) # A full request isn't needed here. site = Mock(spec=["site_tag", "server_version_string", "getResourceFor"]) site.site_tag = "test-site" site.server_version_string = "Server v1" site.reactor = Mock() request = SynapseRequest(FakeChannel(site, None), site) # Call requestReceived to finish instantiating the object. request.content = BytesIO() # Partially skip some of the internal processing of SynapseRequest. request._started_processing = Mock() request.request_metrics = Mock(spec=["name"]) with patch.object(Request, "render"): request.requestReceived(b"POST", b"/_matrix/client/versions", b"1.1") # Also set the requester to ensure the processing works. request.requester = "@foo:test" with LoggingContext( request.get_request_id(), parent_context=request.logcontext ): logger.info("Hello there, %s!", "wally") log = self.get_log_line() # The terse logger includes additional request information, if possible. expected_log_keys = [ "log", "level", "namespace", "request", "ip_address", "site_tag", "requester", "authenticated_entity", "method", "url", "protocol", "user_agent", ] self.assertCountEqual(log.keys(), expected_log_keys) self.assertEqual(log["log"], "Hello there, wally!") self.assertTrue(log["request"].startswith("POST-")) self.assertEqual(log["ip_address"], "127.0.0.1") self.assertEqual(log["site_tag"], "test-site") self.assertEqual(log["requester"], "@foo:test") self.assertEqual(log["authenticated_entity"], "@foo:test") self.assertEqual(log["method"], "POST") self.assertEqual(log["url"], "/_matrix/client/versions") self.assertEqual(log["protocol"], "1.1") self.assertEqual(log["user_agent"], "")
async def post_json(destination, path, data): self.assertEqual(destination, self.hs.hostname) self.assertEqual( path, "/_matrix/key/v2/query", ) channel = FakeChannel(self.site, self.reactor) req = SynapseRequest(channel) req.content = BytesIO(encode_canonical_json(data)) req.requestReceived( b"POST", path.encode("utf-8"), b"1.1", ) channel.await_result() self.assertEqual(channel.code, 200) resp = channel.json_body return resp
def make_notary_request(self, server_name: str, key_id: str) -> dict: """Send a GET request to the test server requesting the given key. Checks that the response is a 200 and returns the decoded json body. """ channel = FakeChannel(self.site, self.reactor) req = SynapseRequest(channel) req.content = BytesIO(b"") req.requestReceived( b"GET", b"/_matrix/key/v2/query/%s/%s" % (server_name.encode("utf-8"), key_id.encode("utf-8")), b"1.1", ) channel.await_result() self.assertEqual(channel.code, 200) resp = channel.json_body return resp
async def post_json( destination: str, path: str, data: Optional[JsonDict] = None) -> Union[JsonDict, list]: self.assertEqual(destination, self.hs.hostname) self.assertEqual( path, "/_matrix/key/v2/query", ) channel = FakeChannel(self.site, self.reactor) # channel is a `FakeChannel` but `HTTPChannel` is expected req = SynapseRequest(channel, self.site) # type: ignore[arg-type] req.content = BytesIO(encode_canonical_json(data)) req.requestReceived( b"POST", path.encode("utf-8"), b"1.1", ) channel.await_result() self.assertEqual(channel.code, 200) resp = channel.json_body return resp
def _test_disconnect( self, reactor: ThreadedMemoryReactorClock, channel: FakeChannel, expect_cancellation: bool, expected_body: Union[bytes, JsonDict], expected_code: Optional[int] = None, ) -> None: """Disconnects an in-flight request and checks the response. Args: reactor: The twisted reactor running the request handler. channel: The `FakeChannel` for the request. expect_cancellation: `True` if request processing is expected to be cancelled, `False` if the request should run to completion. expected_body: The expected response for the request. expected_code: The expected status code for the request. Defaults to `200` or `499` depending on `expect_cancellation`. """ # Determine the expected status code. if expected_code is None: if expect_cancellation: expected_code = HTTP_STATUS_REQUEST_CANCELLED else: expected_code = HTTPStatus.OK request = channel.request self.assertFalse( channel.is_finished(), "Request finished before we could disconnect - " "was `await_result=False` passed to `make_request`?", ) # We're about to disconnect the request. This also disconnects the channel, so # we have to rely on mocks to extract the response. respond_method: Callable[..., Any] if isinstance(expected_body, bytes): respond_method = respond_with_html_bytes else: respond_method = respond_with_json with mock.patch(f"synapse.http.server.{respond_method.__name__}", wraps=respond_method) as respond_mock: # Disconnect the request. request.connectionLost(reason=ConnectionDone()) if expect_cancellation: # An immediate cancellation is expected. respond_mock.assert_called_once() args, _kwargs = respond_mock.call_args code, body = args[1], args[2] self.assertEqual(code, expected_code) self.assertEqual(request.code, expected_code) self.assertEqual(body, expected_body) else: respond_mock.assert_not_called() # The handler is expected to run to completion. reactor.pump([1.0]) respond_mock.assert_called_once() args, _kwargs = respond_mock.call_args code, body = args[1], args[2] self.assertEqual(code, expected_code) self.assertEqual(request.code, expected_code) self.assertEqual(body, expected_body)