diff --git a/CHANGES/4189.feature b/CHANGES/4189.feature new file mode 100644 index 00000000000..02d227cf0b1 --- /dev/null +++ b/CHANGES/4189.feature @@ -0,0 +1 @@ +Implement BaseRequest.get_extra_info() to access a protocol transports' extra info. diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index a918fd456a2..e23b1174c31 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -199,6 +199,7 @@ Pepe Osca Philipp A. Pieter van Beek Rafael Viotti +Raphael Bialon Raúl Cumplido Required Field Robert Lu diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py index 358f9dab820..3b6c7d0c235 100644 --- a/aiohttp/web_request.py +++ b/aiohttp/web_request.py @@ -669,6 +669,18 @@ async def post(self) -> 'MultiDictProxy[Union[str, bytes, FileField]]': self._post = MultiDictProxy(out) return self._post + def get_extra_info(self, name: str, default: Any = None) -> Any: + """Extra info from protocol transport""" + protocol = self._protocol + if protocol is None: + return default + + transport = protocol.transport + if transport is None: + return default + + return transport.get_extra_info(name, default) + def __repr__(self) -> str: ascii_encodable_path = self.path.encode('ascii', 'backslashreplace') \ .decode('ascii') diff --git a/docs/web_reference.rst b/docs/web_reference.rst index 55118bffb2b..7811c07d503 100644 --- a/docs/web_reference.rst +++ b/docs/web_reference.rst @@ -364,6 +364,18 @@ and :ref:`aiohttp-web-signals` handlers. :return: a cloned :class:`Request` instance. + .. method:: get_extra_info(name, default=None) + + Reads extra information from the protocol's transport. + If no value associated with ``name`` is found, ``default`` is returned. + + :param str name: The key to look up in the transport extra information. + + :param default: Default value to be used when no value for ``name`` is + found (default is ``None``). + + .. versionadded:: 3.7 + .. comethod:: read() Read request body, returns :class:`bytes` object with body content. diff --git a/tests/test_web_request.py b/tests/test_web_request.py index f3622d085c4..123895ddfd8 100644 --- a/tests/test_web_request.py +++ b/tests/test_web_request.py @@ -1,6 +1,7 @@ import asyncio import socket from collections.abc import MutableMapping +from typing import Any from unittest import mock import pytest @@ -684,6 +685,31 @@ def test_url_https_with_closed_transport() -> None: assert str(req.url).startswith('https://') +async def test_get_extra_info() -> None: + valid_key = 'test' + valid_value = 'existent' + default_value = 'default' + + def get_extra_info(name: str, default: Any = None): + return {valid_key: valid_value}.get(name, default) + transp = mock.Mock() + transp.get_extra_info.side_effect = get_extra_info + req = make_mocked_request('GET', '/', transport=transp) + + req_extra_info = req.get_extra_info(valid_key, default_value) + transp_extra_info = req._protocol.transport.get_extra_info(valid_key, + default_value) + assert req_extra_info == transp_extra_info + + req._protocol.transport = None + extra_info = req.get_extra_info(valid_key, default_value) + assert extra_info == default_value + + req._protocol = None + extra_info = req.get_extra_info(valid_key, default_value) + assert extra_info == default_value + + def test_eq() -> None: req1 = make_mocked_request('GET', '/path/to?a=1&b=2') req2 = make_mocked_request('GET', '/path/to?a=1&b=2')