{
    "file_diffs": [
        {
            "old_file_content": "",
            "new_file_content": "Fixed changing scheme/host in ``Response.clone()`` for absolute URLs -- by :user:`Dreamsorcerer`.\n",
            "header": {
                "file": {
                    "path": "CHANGES/8990.bugfix.rst"
                },
                "misc_line": "new file mode 100644"
            },
            "index_line": {
                "old_commit_hash": "00000000",
                "new_commit_hash": "9a978310",
                "mode": ""
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "/dev/null"
            },
            "plus_file": {
                "path": "b/CHANGES/8990.bugfix.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 0,
                            "length": 0
                        },
                        "new_range": {
                            "start": 1,
                            "length": null
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Fixed changing scheme/host in ``Response.clone()`` for absolute URLs -- by :user:`Dreamsorcerer`.",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport datetime\nimport io\nimport re\nimport socket\nimport string\nimport tempfile\nimport types\nimport warnings\nfrom http.cookies import SimpleCookie\nfrom types import MappingProxyType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    Final,\n    Iterator,\n    Mapping,\n    MutableMapping,\n    Optional,\n    Pattern,\n    Tuple,\n    Union,\n    cast,\n)\nfrom urllib.parse import parse_qsl\n\nimport attr\nfrom multidict import (\n    CIMultiDict,\n    CIMultiDictProxy,\n    MultiDict,\n    MultiDictProxy,\n    MultiMapping,\n)\nfrom yarl import URL\n\nfrom . import hdrs\nfrom .abc import AbstractStreamWriter\nfrom .helpers import (\n    _SENTINEL,\n    DEBUG,\n    ETAG_ANY,\n    LIST_QUOTED_ETAG_RE,\n    ChainMapProxy,\n    ETag,\n    HeadersMixin,\n    parse_http_date,\n    reify,\n    sentinel,\n    set_exception,\n)\nfrom .http_parser import RawRequestMessage\nfrom .http_writer import HttpVersion\nfrom .multipart import BodyPartReader, MultipartReader\nfrom .streams import EmptyStreamReader, StreamReader\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    JSONDecoder,\n    LooseHeaders,\n    RawHeaders,\n    StrOrURL,\n)\nfrom .web_exceptions import HTTPRequestEntityTooLarge\nfrom .web_response import StreamResponse\n\n__all__ = (\"BaseRequest\", \"FileField\", \"Request\")\n\n\nif TYPE_CHECKING:\n    from .web_app import Application\n    from .web_protocol import RequestHandler\n    from .web_urldispatcher import UrlMappingMatchInfo\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass FileField:\n    name: str\n    filename: str\n    file: io.BufferedReader\n    content_type: str\n    headers: CIMultiDictProxy[str]\n\n\n_TCHAR: Final[str] = string.digits + string.ascii_letters + r\"!#$%&'*+.^_`|~-\"\n# '-' at the end to prevent interpretation as range in a char class\n\n_TOKEN: Final[str] = rf\"[{_TCHAR}]+\"\n\n_QDTEXT: Final[str] = r\"[{}]\".format(\n    r\"\".join(chr(c) for c in (0x09, 0x20, 0x21) + tuple(range(0x23, 0x7F)))\n)\n# qdtext includes 0x5C to escape 0x5D ('\\]')\n# qdtext excludes obs-text (because obsoleted, and encoding not specified)\n\n_QUOTED_PAIR: Final[str] = r\"\\\\[\\t !-~]\"\n\n_QUOTED_STRING: Final[str] = r'\"(?:{quoted_pair}|{qdtext})*\"'.format(\n    qdtext=_QDTEXT, quoted_pair=_QUOTED_PAIR\n)\n\n_FORWARDED_PAIR: Final[str] = (\n    r\"({token})=({token}|{quoted_string})(:\\d{{1,4}})?\".format(\n        token=_TOKEN, quoted_string=_QUOTED_STRING\n    )\n)\n\n_QUOTED_PAIR_REPLACE_RE: Final[Pattern[str]] = re.compile(r\"\\\\([\\t !-~])\")\n# same pattern as _QUOTED_PAIR but contains a capture group\n\n_FORWARDED_PAIR_RE: Final[Pattern[str]] = re.compile(_FORWARDED_PAIR)\n\n############################################################\n# HTTP Request\n############################################################\n\n\nclass BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if scheme is not None:\n            self._cache[\"scheme\"] = scheme\n        if host is not None:\n            self._cache[\"host\"] = host\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()\n\n\nclass Request(BaseRequest):\n\n    ATTRS = BaseRequest.ATTRS | frozenset([\"_match_info\"])\n\n    def __init__(self, *args: Any, **kwargs: Any) -> None:\n        super().__init__(*args, **kwargs)\n\n        # matchdict, route_name, handler\n        # or information about traversal lookup\n\n        # initialized after route resolving\n        self._match_info: Optional[UrlMappingMatchInfo] = None\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom {}.{} attribute \"\n                    \"is discouraged\".format(self.__class__.__name__, name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"Request\":\n        ret = super().clone(\n            method=method,\n            rel_url=rel_url,\n            headers=headers,\n            scheme=scheme,\n            host=host,\n            remote=remote,\n            client_max_size=client_max_size,\n        )\n        new_ret = cast(Request, ret)\n        new_ret._match_info = self._match_info\n        return new_ret\n\n    @reify\n    def match_info(self) -> \"UrlMappingMatchInfo\":\n        \"\"\"Result of route resolving.\"\"\"\n        match_info = self._match_info\n        assert match_info is not None\n        return match_info\n\n    @property\n    def app(self) -> \"Application\":\n        \"\"\"Application instance.\"\"\"\n        match_info = self._match_info\n        assert match_info is not None\n        return match_info.current_app\n\n    @property\n    def config_dict(self) -> ChainMapProxy:\n        match_info = self._match_info\n        assert match_info is not None\n        lst = match_info.apps\n        app = self.app\n        idx = lst.index(app)\n        sublist = list(reversed(lst[: idx + 1]))\n        return ChainMapProxy(sublist)\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        match_info = self._match_info\n        if match_info is None:\n            return\n        for app in match_info._apps:\n            await app.on_response_prepare.send(self, response)\n",
            "new_file_content": "import asyncio\nimport datetime\nimport io\nimport re\nimport socket\nimport string\nimport tempfile\nimport types\nimport warnings\nfrom http.cookies import SimpleCookie\nfrom types import MappingProxyType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    Final,\n    Iterator,\n    Mapping,\n    MutableMapping,\n    Optional,\n    Pattern,\n    Tuple,\n    Union,\n    cast,\n)\nfrom urllib.parse import parse_qsl\n\nimport attr\nfrom multidict import (\n    CIMultiDict,\n    CIMultiDictProxy,\n    MultiDict,\n    MultiDictProxy,\n    MultiMapping,\n)\nfrom yarl import URL\n\nfrom . import hdrs\nfrom .abc import AbstractStreamWriter\nfrom .helpers import (\n    _SENTINEL,\n    DEBUG,\n    ETAG_ANY,\n    LIST_QUOTED_ETAG_RE,\n    ChainMapProxy,\n    ETag,\n    HeadersMixin,\n    parse_http_date,\n    reify,\n    sentinel,\n    set_exception,\n)\nfrom .http_parser import RawRequestMessage\nfrom .http_writer import HttpVersion\nfrom .multipart import BodyPartReader, MultipartReader\nfrom .streams import EmptyStreamReader, StreamReader\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    JSONDecoder,\n    LooseHeaders,\n    RawHeaders,\n    StrOrURL,\n)\nfrom .web_exceptions import HTTPRequestEntityTooLarge\nfrom .web_response import StreamResponse\n\n__all__ = (\"BaseRequest\", \"FileField\", \"Request\")\n\n\nif TYPE_CHECKING:\n    from .web_app import Application\n    from .web_protocol import RequestHandler\n    from .web_urldispatcher import UrlMappingMatchInfo\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass FileField:\n    name: str\n    filename: str\n    file: io.BufferedReader\n    content_type: str\n    headers: CIMultiDictProxy[str]\n\n\n_TCHAR: Final[str] = string.digits + string.ascii_letters + r\"!#$%&'*+.^_`|~-\"\n# '-' at the end to prevent interpretation as range in a char class\n\n_TOKEN: Final[str] = rf\"[{_TCHAR}]+\"\n\n_QDTEXT: Final[str] = r\"[{}]\".format(\n    r\"\".join(chr(c) for c in (0x09, 0x20, 0x21) + tuple(range(0x23, 0x7F)))\n)\n# qdtext includes 0x5C to escape 0x5D ('\\]')\n# qdtext excludes obs-text (because obsoleted, and encoding not specified)\n\n_QUOTED_PAIR: Final[str] = r\"\\\\[\\t !-~]\"\n\n_QUOTED_STRING: Final[str] = r'\"(?:{quoted_pair}|{qdtext})*\"'.format(\n    qdtext=_QDTEXT, quoted_pair=_QUOTED_PAIR\n)\n\n_FORWARDED_PAIR: Final[str] = (\n    r\"({token})=({token}|{quoted_string})(:\\d{{1,4}})?\".format(\n        token=_TOKEN, quoted_string=_QUOTED_STRING\n    )\n)\n\n_QUOTED_PAIR_REPLACE_RE: Final[Pattern[str]] = re.compile(r\"\\\\([\\t !-~])\")\n# same pattern as _QUOTED_PAIR but contains a capture group\n\n_FORWARDED_PAIR_RE: Final[Pattern[str]] = re.compile(_FORWARDED_PAIR)\n\n############################################################\n# HTTP Request\n############################################################\n\n\nclass BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            if scheme is not None:\n                url = url.with_scheme(scheme)\n            if host is not None:\n                url = url.with_host(host)\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n            if scheme is not None:\n                self._cache[\"scheme\"] = scheme\n            if host is not None:\n                self._cache[\"host\"] = host\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()\n\n\nclass Request(BaseRequest):\n\n    ATTRS = BaseRequest.ATTRS | frozenset([\"_match_info\"])\n\n    def __init__(self, *args: Any, **kwargs: Any) -> None:\n        super().__init__(*args, **kwargs)\n\n        # matchdict, route_name, handler\n        # or information about traversal lookup\n\n        # initialized after route resolving\n        self._match_info: Optional[UrlMappingMatchInfo] = None\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom {}.{} attribute \"\n                    \"is discouraged\".format(self.__class__.__name__, name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"Request\":\n        ret = super().clone(\n            method=method,\n            rel_url=rel_url,\n            headers=headers,\n            scheme=scheme,\n            host=host,\n            remote=remote,\n            client_max_size=client_max_size,\n        )\n        new_ret = cast(Request, ret)\n        new_ret._match_info = self._match_info\n        return new_ret\n\n    @reify\n    def match_info(self) -> \"UrlMappingMatchInfo\":\n        \"\"\"Result of route resolving.\"\"\"\n        match_info = self._match_info\n        assert match_info is not None\n        return match_info\n\n    @property\n    def app(self) -> \"Application\":\n        \"\"\"Application instance.\"\"\"\n        match_info = self._match_info\n        assert match_info is not None\n        return match_info.current_app\n\n    @property\n    def config_dict(self) -> ChainMapProxy:\n        match_info = self._match_info\n        assert match_info is not None\n        lst = match_info.apps\n        app = self.app\n        idx = lst.index(app)\n        sublist = list(reversed(lst[: idx + 1]))\n        return ChainMapProxy(sublist)\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        match_info = self._match_info\n        if match_info is None:\n            return\n        for app in match_info._apps:\n            await app.on_response_prepare.send(self, response)\n",
            "header": {
                "file": {
                    "path": "aiohttp/web_request.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "a63d3074",
                "new_commit_hash": "1d94c576",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/aiohttp/web_request.py"
            },
            "plus_file": {
                "path": "b/aiohttp/web_request.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 175,
                            "length": 6
                        },
                        "new_range": {
                            "start": 175,
                            "length": 10
                        },
                        "section": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self._cache: Dict[str, Any] = {}",
                                "type": "context"
                            },
                            {
                                "content": "        url = message.url",
                                "type": "context"
                            },
                            {
                                "content": "        if url.is_absolute():",
                                "type": "context"
                            },
                            {
                                "content": "            if scheme is not None:",
                                "type": "added"
                            },
                            {
                                "content": "                url = url.with_scheme(scheme)",
                                "type": "added"
                            },
                            {
                                "content": "            if host is not None:",
                                "type": "added"
                            },
                            {
                                "content": "                url = url.with_host(host)",
                                "type": "added"
                            },
                            {
                                "content": "            # absolute URL is given,",
                                "type": "context"
                            },
                            {
                                "content": "            # override auto-calculating url, host, and scheme",
                                "type": "context"
                            },
                            {
                                "content": "            # all other properties should be good",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/web_request.py",
                            "type": "method",
                            "name": "BaseRequest.__init__",
                            "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            if scheme is not None:\n                url = url.with_scheme(scheme)\n            if host is not None:\n                url = url.with_host(host)\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n            if scheme is not None:\n                self._cache[\"scheme\"] = scheme\n            if host is not None:\n                self._cache[\"host\"] = host\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 150,
                            "end_lineno": 209,
                            "parent": {
                                "file_name": "aiohttp/web_request.py",
                                "type": "class",
                                "name": "BaseRequest",
                                "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            if scheme is not None:\n                url = url.with_scheme(scheme)\n            if host is not None:\n                url = url.with_host(host)\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n            if scheme is not None:\n                self._cache[\"scheme\"] = scheme\n            if host is not None:\n                self._cache[\"host\"] = host\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 118,
                                "end_lineno": 837,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/web_request.py",
                            "type": "class",
                            "name": "BaseRequest",
                            "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            if scheme is not None:\n                url = url.with_scheme(scheme)\n            if host is not None:\n                url = url.with_host(host)\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n            if scheme is not None:\n                self._cache[\"scheme\"] = scheme\n            if host is not None:\n                self._cache[\"host\"] = host\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 118,
                            "end_lineno": 837,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 184,
                            "length": 6
                        },
                        "new_range": {
                            "start": 188,
                            "length": 10
                        },
                        "section": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            self._rel_url = url.relative()",
                                "type": "context"
                            },
                            {
                                "content": "        else:",
                                "type": "context"
                            },
                            {
                                "content": "            self._rel_url = message.url",
                                "type": "context"
                            },
                            {
                                "content": "            if scheme is not None:",
                                "type": "added"
                            },
                            {
                                "content": "                self._cache[\"scheme\"] = scheme",
                                "type": "added"
                            },
                            {
                                "content": "            if host is not None:",
                                "type": "added"
                            },
                            {
                                "content": "                self._cache[\"host\"] = host",
                                "type": "added"
                            },
                            {
                                "content": "        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None",
                                "type": "context"
                            },
                            {
                                "content": "        self._read_bytes: Optional[bytes] = None",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/web_request.py",
                            "type": "method",
                            "name": "BaseRequest.__init__",
                            "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            if scheme is not None:\n                url = url.with_scheme(scheme)\n            if host is not None:\n                url = url.with_host(host)\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n            if scheme is not None:\n                self._cache[\"scheme\"] = scheme\n            if host is not None:\n                self._cache[\"host\"] = host\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 150,
                            "end_lineno": 209,
                            "parent": {
                                "file_name": "aiohttp/web_request.py",
                                "type": "class",
                                "name": "BaseRequest",
                                "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            if scheme is not None:\n                url = url.with_scheme(scheme)\n            if host is not None:\n                url = url.with_host(host)\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n            if scheme is not None:\n                self._cache[\"scheme\"] = scheme\n            if host is not None:\n                self._cache[\"host\"] = host\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 118,
                                "end_lineno": 837,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/web_request.py",
                            "type": "class",
                            "name": "BaseRequest",
                            "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            if scheme is not None:\n                url = url.with_scheme(scheme)\n            if host is not None:\n                url = url.with_host(host)\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n            if scheme is not None:\n                self._cache[\"scheme\"] = scheme\n            if host is not None:\n                self._cache[\"host\"] = host\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 118,
                            "end_lineno": 837,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 197,
                            "length": 10
                        },
                        "new_range": {
                            "start": 205,
                            "length": 6
                        },
                        "section": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")",
                                "type": "context"
                            },
                            {
                                "content": "        self._transport_peername = transport.get_extra_info(\"peername\")",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if scheme is not None:",
                                "type": "deleted"
                            },
                            {
                                "content": "            self._cache[\"scheme\"] = scheme",
                                "type": "deleted"
                            },
                            {
                                "content": "        if host is not None:",
                                "type": "deleted"
                            },
                            {
                                "content": "            self._cache[\"host\"] = host",
                                "type": "deleted"
                            },
                            {
                                "content": "        if remote is not None:",
                                "type": "context"
                            },
                            {
                                "content": "            self._cache[\"remote\"] = remote",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/web_request.py",
                            "type": "method",
                            "name": "BaseRequest.__init__",
                            "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if scheme is not None:\n            self._cache[\"scheme\"] = scheme\n        if host is not None:\n            self._cache[\"host\"] = host\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 150,
                            "end_lineno": 205,
                            "parent": {
                                "file_name": "aiohttp/web_request.py",
                                "type": "class",
                                "name": "BaseRequest",
                                "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if scheme is not None:\n            self._cache[\"scheme\"] = scheme\n        if host is not None:\n            self._cache[\"host\"] = host\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 118,
                                "end_lineno": 833,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/web_request.py",
                            "type": "class",
                            "name": "BaseRequest",
                            "content": "class BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if scheme is not None:\n            self._cache[\"scheme\"] = scheme\n        if host is not None:\n            self._cache[\"host\"] = host\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 118,
                            "end_lineno": 833,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport datetime\nimport socket\nfrom collections.abc import MutableMapping\nfrom typing import Any\nfrom unittest import mock\n\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy, MultiDict\nfrom yarl import URL\n\nfrom aiohttp import HttpVersion\nfrom aiohttp.http_parser import RawRequestMessage\nfrom aiohttp.streams import StreamReader\nfrom aiohttp.test_utils import make_mocked_request\nfrom aiohttp.web import BaseRequest, HTTPRequestEntityTooLarge\nfrom aiohttp.web_request import ETag\n\n\n@pytest.fixture\ndef protocol():\n    return mock.Mock(_reading_paused=False)\n\n\ndef test_base_ctor() -> None:\n    message = RawRequestMessage(\n        \"GET\",\n        \"/path/to?a=1&b=2\",\n        HttpVersion(1, 1),\n        CIMultiDictProxy(CIMultiDict()),\n        (),\n        False,\n        False,\n        False,\n        False,\n        URL(\"/path/to?a=1&b=2\"),\n    )\n\n    req = BaseRequest(\n        message, mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock()\n    )\n\n    assert \"GET\" == req.method\n    assert HttpVersion(1, 1) == req.version\n    # MacOS may return CamelCased host name, need .lower()\n    # FQDN can be wider than host, e.g.\n    # 'fv-az397-495' in 'fv-az397-495.internal.cloudapp.net'\n    assert req.host.lower() in socket.getfqdn().lower()\n    assert \"/path/to?a=1&b=2\" == req.path_qs\n    assert \"/path/to\" == req.path\n    assert \"a=1&b=2\" == req.query_string\n    assert CIMultiDict() == req.headers\n    assert () == req.raw_headers\n\n    get = req.query\n    assert MultiDict([(\"a\", \"1\"), (\"b\", \"2\")]) == get\n    # second call should return the same object\n    assert get is req.query\n\n    assert req.keep_alive\n\n    assert req\n\n\ndef test_ctor() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n\n    assert \"GET\" == req.method\n    assert HttpVersion(1, 1) == req.version\n    # MacOS may return CamelCased host name, need .lower()\n    # FQDN can be wider than host, e.g.\n    # 'fv-az397-495' in 'fv-az397-495.internal.cloudapp.net'\n    assert req.host.lower() in socket.getfqdn().lower()\n    assert \"/path/to?a=1&b=2\" == req.path_qs\n    assert \"/path/to\" == req.path\n    assert \"a=1&b=2\" == req.query_string\n    assert CIMultiDict() == req.headers\n    assert () == req.raw_headers\n\n    get = req.query\n    assert MultiDict([(\"a\", \"1\"), (\"b\", \"2\")]) == get\n    # second call should return the same object\n    assert get is req.query\n\n    assert req.keep_alive\n\n    # just make sure that all lines of make_mocked_request covered\n    headers = CIMultiDict(FOO=\"bar\")\n    payload = mock.Mock()\n    protocol = mock.Mock()\n    app = mock.Mock()\n    req = make_mocked_request(\n        \"GET\",\n        \"/path/to?a=1&b=2\",\n        headers=headers,\n        protocol=protocol,\n        payload=payload,\n        app=app,\n    )\n    assert req.app is app\n    assert req.content is payload\n    assert req.protocol is protocol\n    assert req.transport is protocol.transport\n    assert req.headers == headers\n    assert req.raw_headers == ((b\"FOO\", b\"bar\"),)\n    assert req.task is req._task\n\n\ndef test_deprecated_message() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    with pytest.deprecated_call(match=r\"^Request\\.message is deprecated$\"):\n        assert req.message == req._message\n\n\ndef test_doubleslashes() -> None:\n    # NB: //foo/bar is an absolute URL with foo netloc and /bar path\n    req = make_mocked_request(\"GET\", \"/bar//foo/\")\n    assert \"/bar//foo/\" == req.path\n\n\ndef test_content_type_not_specified() -> None:\n    req = make_mocked_request(\"Get\", \"/\")\n    assert \"application/octet-stream\" == req.content_type\n\n\ndef test_content_type_from_spec() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"application/json\")])\n    )\n    assert \"application/json\" == req.content_type\n\n\ndef test_content_type_from_spec_with_charset() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"text/html; charset=UTF-8\")])\n    )\n    assert \"text/html\" == req.content_type\n    assert \"UTF-8\" == req.charset\n\n\ndef test_calc_content_type_on_getting_charset() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"text/html; charset=UTF-8\")])\n    )\n    assert \"UTF-8\" == req.charset\n    assert \"text/html\" == req.content_type\n\n\ndef test_urlencoded_querystring() -> None:\n    req = make_mocked_request(\"GET\", \"/yandsearch?text=%D1%82%D0%B5%D0%BA%D1%81%D1%82\")\n    assert {\"text\": \"текст\"} == req.query\n\n\ndef test_non_ascii_path() -> None:\n    req = make_mocked_request(\"GET\", \"/путь\")\n    assert \"/путь\" == req.path\n\n\ndef test_non_ascii_raw_path() -> None:\n    req = make_mocked_request(\"GET\", \"/путь\")\n    assert \"/путь\" == req.raw_path\n\n\ndef test_absolute_url() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.url == URL(\"https://example.com/path/to?a=1\")\n    assert req.scheme == \"https\"\n    assert req.host == \"example.com\"\n    assert req.rel_url == URL.build(path=\"/path/to\", query={\"a\": \"1\"})\n\n\ndef test_content_length() -> None:\n    req = make_mocked_request(\"Get\", \"/\", CIMultiDict([(\"CONTENT-LENGTH\", \"123\")]))\n\n    assert 123 == req.content_length\n\n\ndef test_range_to_slice_head() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=0-499\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[:500]\n\n\ndef test_range_to_slice_mid() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=500-999\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[500:1000]\n\n\ndef test_range_to_slice_tail_start() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=9500-\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[-500:]\n\n\ndef test_range_to_slice_tail_stop() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=-500\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[-500:]\n\n\ndef test_non_keepalive_on_http10() -> None:\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion(1, 0))\n    assert not req.keep_alive\n\n\ndef test_non_keepalive_on_closing() -> None:\n    req = make_mocked_request(\"GET\", \"/\", closing=True)\n    assert not req.keep_alive\n\n\nasync def test_call_POST_on_GET_request() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    ret = await req.post()\n    assert CIMultiDict() == ret\n\n\nasync def test_call_POST_on_weird_content_type() -> None:\n    req = make_mocked_request(\n        \"POST\", \"/\", headers=CIMultiDict({\"CONTENT-TYPE\": \"something/weird\"})\n    )\n\n    ret = await req.post()\n    assert CIMultiDict() == ret\n\n\nasync def test_call_POST_twice() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    ret1 = await req.post()\n    ret2 = await req.post()\n    assert ret1 is ret2\n\n\ndef test_no_request_cookies() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    assert req.cookies == {}\n\n    cookies = req.cookies\n    assert cookies is req.cookies\n\n\ndef test_request_cookie() -> None:\n    headers = CIMultiDict(COOKIE=\"cookie1=value1; cookie2=value2\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n\n    assert req.cookies == {\"cookie1\": \"value1\", \"cookie2\": \"value2\"}\n\n\ndef test_request_cookie__set_item() -> None:\n    headers = CIMultiDict(COOKIE=\"name=value\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n\n    assert req.cookies == {\"name\": \"value\"}\n\n    with pytest.raises(TypeError):\n        req.cookies[\"my\"] = \"value\"\n\n\ndef test_match_info() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req._match_info is req.match_info\n\n\ndef test_request_is_mutable_mapping() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert isinstance(req, MutableMapping)\n    req[\"key\"] = \"value\"\n    assert \"value\" == req[\"key\"]\n\n\ndef test_request_delitem() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"value\"\n    assert \"value\" == req[\"key\"]\n    del req[\"key\"]\n    assert \"key\" not in req\n\n\ndef test_request_len() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert len(req) == 0\n    req[\"key\"] = \"value\"\n    assert len(req) == 1\n\n\ndef test_request_iter() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"value\"\n    req[\"key2\"] = \"value2\"\n    assert set(req) == {\"key\", \"key2\"}\n\n\ndef test___repr__() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to\")\n    assert \"<Request GET /path/to >\" == repr(req)\n\n\ndef test___repr___non_ascii_path() -> None:\n    req = make_mocked_request(\"GET\", \"/path/\\U0001f415\\U0001f308\")\n    assert \"<Request GET /path/\\\\U0001f415\\\\U0001f308 >\" == repr(req)\n\n\ndef test_http_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={\"Host\": \"example.com\"})\n    assert \"http\" == req.scheme\n    assert req.secure is False\n\n\ndef test_https_scheme_by_ssl_transport() -> None:\n    req = make_mocked_request(\n        \"GET\", \"/\", headers={\"Host\": \"example.com\"}, sslcontext=True\n    )\n    assert \"https\" == req.scheme\n    assert req.secure is True\n\n\ndef test_single_forwarded_header() -> None:\n    header = \"by=identifier;for=identifier;host=identifier;proto=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"host\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"identifier\"\n\n\n@pytest.mark.parametrize(\n    \"forward_for_in, forward_for_out\",\n    [\n        (\"1.2.3.4:1234\", \"1.2.3.4:1234\"),\n        (\"1.2.3.4\", \"1.2.3.4\"),\n        ('\"[2001:db8:cafe::17]:1234\"', \"[2001:db8:cafe::17]:1234\"),\n        ('\"[2001:db8:cafe::17]\"', \"[2001:db8:cafe::17]\"),\n    ],\n)\ndef test_forwarded_node_identifier(forward_for_in, forward_for_out) -> None:\n    header = f\"for={forward_for_in}\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded == ({\"for\": forward_for_out},)\n\n\ndef test_single_forwarded_header_camelcase() -> None:\n    header = \"bY=identifier;fOr=identifier;HOst=identifier;pRoTO=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"host\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"identifier\"\n\n\ndef test_single_forwarded_header_single_param() -> None:\n    header = \"BY=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n\n\ndef test_single_forwarded_header_multiple_param() -> None:\n    header = \"By=identifier1,BY=identifier2,  By=identifier3 ,  BY=identifier4\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 4\n    assert req.forwarded[0][\"by\"] == \"identifier1\"\n    assert req.forwarded[1][\"by\"] == \"identifier2\"\n    assert req.forwarded[2][\"by\"] == \"identifier3\"\n    assert req.forwarded[3][\"by\"] == \"identifier4\"\n\n\ndef test_single_forwarded_header_quoted_escaped() -> None:\n    header = r'BY=identifier;pROTO=\"\\lala lan\\d\\~ 123\\!&\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"lala land~ 123!&\"\n\n\ndef test_single_forwarded_header_custom_param() -> None:\n    header = r'BY=identifier;PROTO=https;SOME=\"other, \\\"value\\\"\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 1\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"https\"\n    assert req.forwarded[0][\"some\"] == 'other, \"value\"'\n\n\ndef test_single_forwarded_header_empty_params() -> None:\n    # This is allowed by the grammar given in RFC 7239\n    header = \";For=identifier;;PROTO=https;;;\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"https\"\n\n\ndef test_single_forwarded_header_bad_separator() -> None:\n    header = \"BY=identifier PROTO=https\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert \"proto\" not in req.forwarded[0]\n\n\ndef test_single_forwarded_header_injection1() -> None:\n    # We might receive a header like this if we're sitting behind a reverse\n    # proxy that blindly appends a forwarded-element without checking\n    # the syntax of existing field-values. We should be able to recover\n    # the appended element anyway.\n    header = 'for=_injected;by=\", for=_real'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 2\n    assert \"by\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n\n\ndef test_single_forwarded_header_injection2() -> None:\n    header = \"very bad syntax, for=_real\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 2\n    assert \"for\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n\n\ndef test_single_forwarded_header_long_quoted_string() -> None:\n    header = 'for=\"' + \"\\\\\\\\\" * 5000 + '\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"for\"] == \"\\\\\" * 5000\n\n\ndef test_multiple_forwarded_headers() -> None:\n    headers = CIMultiDict()\n    headers.add(\"Forwarded\", \"By=identifier1;for=identifier2, BY=identifier3\")\n    headers.add(\"Forwarded\", \"By=identifier4;fOr=identifier5\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 3\n    assert req.forwarded[0][\"by\"] == \"identifier1\"\n    assert req.forwarded[0][\"for\"] == \"identifier2\"\n    assert req.forwarded[1][\"by\"] == \"identifier3\"\n    assert req.forwarded[2][\"by\"] == \"identifier4\"\n    assert req.forwarded[2][\"for\"] == \"identifier5\"\n\n\ndef test_multiple_forwarded_headers_bad_syntax() -> None:\n    headers = CIMultiDict()\n    headers.add(\"Forwarded\", \"for=_1;by=_2\")\n    headers.add(\"Forwarded\", \"invalid value\")\n    headers.add(\"Forwarded\", \"\")\n    headers.add(\"Forwarded\", \"for=_3;by=_4\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 4\n    assert req.forwarded[0][\"for\"] == \"_1\"\n    assert \"for\" not in req.forwarded[1]\n    assert \"for\" not in req.forwarded[2]\n    assert req.forwarded[3][\"by\"] == \"_4\"\n\n\ndef test_multiple_forwarded_headers_injection() -> None:\n    headers = CIMultiDict()\n    # This could be sent by an attacker, hoping to \"shadow\" the second header.\n    headers.add(\"Forwarded\", 'for=_injected;by=\"')\n    # This is added by our trusted reverse proxy.\n    headers.add(\"Forwarded\", \"for=_real;by=_actual_proxy\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 2\n    assert \"by\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n    assert req.forwarded[1][\"by\"] == \"_actual_proxy\"\n\n\ndef test_host_by_host_header() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Host\": \"example.com\"}))\n    assert req.host == \"example.com\"\n\n\ndef test_raw_headers() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"X-HEADER\": \"aaa\"}))\n    assert req.raw_headers == ((b\"X-HEADER\", b\"aaa\"),)\n\n\ndef test_rel_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    assert URL(\"/path\") == req.rel_url\n\n\ndef test_url_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"HOST\": \"example.com\"})\n    assert URL(\"http://example.com/path\") == req.url\n\n\ndef test_clone() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone()\n    assert req2.method == \"GET\"\n    assert req2.rel_url == URL(\"/path\")\n\n\ndef test_clone_client_max_size() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", client_max_size=1024)\n    req2 = req.clone()\n    assert req._client_max_size == req2._client_max_size\n    assert req2._client_max_size == 1024\n\n\ndef test_clone_override_client_max_size() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", client_max_size=1024)\n    req2 = req.clone(client_max_size=2048)\n    assert req2.client_max_size == 2048\n\n\ndef test_clone_method() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(method=\"POST\")\n    assert req2.method == \"POST\"\n    assert req2.rel_url == URL(\"/path\")\n\n\ndef test_clone_rel_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(rel_url=URL(\"/path2\"))\n    assert req2.rel_url == URL(\"/path2\")\n\n\ndef test_clone_rel_url_str() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(rel_url=\"/path2\")\n    assert req2.rel_url == URL(\"/path2\")\n\n\ndef test_clone_headers() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"A\": \"B\"})\n    req2 = req.clone(headers=CIMultiDict({\"B\": \"C\"}))\n    assert req2.headers == CIMultiDict({\"B\": \"C\"})\n    assert req2.raw_headers == ((b\"B\", b\"C\"),)\n\n\ndef test_clone_headers_dict() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"A\": \"B\"})\n    req2 = req.clone(headers={\"B\": \"C\"})\n    assert req2.headers == CIMultiDict({\"B\": \"C\"})\n    assert req2.raw_headers == ((b\"B\", b\"C\"),)\n\n\nasync def test_cannot_clone_after_read(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(b\"data\")\n    payload.feed_eof()\n    req = make_mocked_request(\"GET\", \"/path\", payload=payload)\n    await req.read()\n    with pytest.raises(RuntimeError):\n        req.clone()\n\n\nasync def test_make_too_big_request(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    req = make_mocked_request(\"POST\", \"/\", payload=payload)\n    with pytest.raises(HTTPRequestEntityTooLarge) as err:\n        await req.read()\n\n    assert err.value.status_code == 413\n\n\nasync def test_make_too_big_request_adjust_limit(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    max_size = 1024**2 + 2\n    req = make_mocked_request(\"POST\", \"/\", payload=payload, client_max_size=max_size)\n    txt = await req.read()\n    assert len(txt) == 1024**2 + 1\n\n\nasync def test_multipart_formdata(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"a\"\\r\\n'\n        b\"\\r\\n\"\n        b\"b\\r\\n\"\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"c\"\\r\\n'\n        b\"\\r\\n\"\n        b\"d\\r\\n\"\n        b\"-----------------------------326931944431359--\\r\\n\"\n    )\n    content_type = (\n        \"multipart/form-data; boundary=\" \"---------------------------326931944431359\"\n    )\n    payload.feed_eof()\n    req = make_mocked_request(\n        \"POST\", \"/\", headers={\"CONTENT-TYPE\": content_type}, payload=payload\n    )\n    result = await req.post()\n    assert dict(result) == {\"a\": \"b\", \"c\": \"d\"}\n\n\nasync def test_multipart_formdata_file(protocol) -> None:\n    # Make sure file uploads work, even without a content type\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"a_file\"; filename=\"binary\"\\r\\n'\n        b\"\\r\\n\"\n        b\"\\ff\\r\\n\"\n        b\"-----------------------------326931944431359--\\r\\n\"\n    )\n    content_type = (\n        \"multipart/form-data; boundary=\" \"---------------------------326931944431359\"\n    )\n    payload.feed_eof()\n    req = make_mocked_request(\n        \"POST\", \"/\", headers={\"CONTENT-TYPE\": content_type}, payload=payload\n    )\n    result = await req.post()\n    assert hasattr(result[\"a_file\"], \"file\")\n    content = result[\"a_file\"].file.read()\n    assert content == b\"\\ff\"\n\n    result[\"a_file\"].file.close()\n\n\nasync def test_make_too_big_request_limit_None(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    max_size = None\n    req = make_mocked_request(\"POST\", \"/\", payload=payload, client_max_size=max_size)\n    txt = await req.read()\n    assert len(txt) == 1024**2 + 1\n\n\ndef test_remote_peername_tcp() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = (\"10.10.10.10\", 1234)\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    assert req.remote == \"10.10.10.10\"\n\n\ndef test_remote_peername_unix() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = \"/path/to/sock\"\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    assert req.remote == \"/path/to/sock\"\n\n\ndef test_save_state_on_clone() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"val\"\n    req2 = req.clone()\n    req2[\"key\"] = \"val2\"\n    assert req[\"key\"] == \"val\"\n    assert req2[\"key\"] == \"val2\"\n\n\ndef test_clone_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req2 = req.clone(scheme=\"https\")\n    assert req2.scheme == \"https\"\n\n\ndef test_clone_host() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req2 = req.clone(host=\"example.com\")\n    assert req2.host == \"example.com\"\n\n\ndef test_clone_remote() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req2 = req.clone(remote=\"11.11.11.11\")\n    assert req2.remote == \"11.11.11.11\"\n\n\ndef test_remote_with_closed_transport() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = (\"10.10.10.10\", 1234)\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    req._protocol = None\n    assert req.remote == \"10.10.10.10\"\n\n\ndef test_url_http_with_closed_transport() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req._protocol = None\n    assert str(req.url).startswith(\"http://\")\n\n\ndef test_url_https_with_closed_transport() -> None:\n    req = make_mocked_request(\"GET\", \"/\", sslcontext=True)\n    req._protocol = None\n    assert str(req.url).startswith(\"https://\")\n\n\nasync def test_get_extra_info() -> None:\n    valid_key = \"test\"\n    valid_value = \"existent\"\n    default_value = \"default\"\n\n    def get_extra_info(name: str, default: Any = None):\n        return {valid_key: valid_value}.get(name, default)\n\n    transp = mock.Mock()\n    transp.get_extra_info.side_effect = get_extra_info\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n\n    req_extra_info = req.get_extra_info(valid_key, default_value)\n    transp_extra_info = req._protocol.transport.get_extra_info(valid_key, default_value)\n    assert req_extra_info == transp_extra_info\n\n    req._protocol.transport = None\n    extra_info = req.get_extra_info(valid_key, default_value)\n    assert extra_info == default_value\n\n    req._protocol = None\n    extra_info = req.get_extra_info(valid_key, default_value)\n    assert extra_info == default_value\n\n\ndef test_eq() -> None:\n    req1 = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    req2 = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    assert req1 != req2\n    assert req1 == req1\n\n\nasync def test_loop_prop() -> None:\n    loop = asyncio.get_event_loop()\n    req = make_mocked_request(\"GET\", \"/path\", loop=loop)\n    with pytest.deprecated_call(match=r\"^request\\.loop property is deprecated$\"):\n        assert req.loop is loop\n\n\n@pytest.mark.parametrize(\n    [\"header\", \"header_attr\"],\n    [\n        pytest.param(\"If-Match\", \"if_match\"),\n        pytest.param(\"If-None-Match\", \"if_none_match\"),\n    ],\n)\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\n            '\"67ab43\", W/\"54ed21\", \"7892,dd\"',\n            (\n                ETag(is_weak=False, value=\"67ab43\"),\n                ETag(is_weak=True, value=\"54ed21\"),\n                ETag(is_weak=False, value=\"7892,dd\"),\n            ),\n        ),\n        pytest.param(\n            '\"bfc1ef-5b2c2730249c88ca92d82d\"',\n            (ETag(is_weak=False, value=\"bfc1ef-5b2c2730249c88ca92d82d\"),),\n        ),\n        pytest.param(\n            '\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"',\n            (\n                ETag(is_weak=False, value=\"valid-tag\"),\n                ETag(is_weak=False, value=\"also-valid-tag\"),\n            ),\n        ),\n        pytest.param(\n            '\"ascii\", \"это точно не ascii\", \"ascii again\"',\n            (ETag(is_weak=False, value=\"ascii\"),),\n        ),\n        pytest.param(\n            \"*\",\n            (ETag(is_weak=False, value=\"*\"),),\n        ),\n    ],\n)\ndef test_etag_headers(header, header_attr, header_val, expected) -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={header: header_val})\n    assert getattr(req, header_attr) == expected\n\n\n@pytest.mark.parametrize(\n    [\"header\", \"header_attr\"],\n    [\n        pytest.param(\"If-Modified-Since\", \"if_modified_since\"),\n        pytest.param(\"If-Unmodified-Since\", \"if_unmodified_since\"),\n        pytest.param(\"If-Range\", \"if_range\"),\n    ],\n)\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\"xxyyzz\", None),\n        pytest.param(\"Tue, 08 Oct 4446413 00:56:40 GMT\", None),\n        pytest.param(\"Tue, 08 Oct 2000 00:56:80 GMT\", None),\n        pytest.param(\n            \"Tue, 08 Oct 2000 00:56:40 GMT\",\n            datetime.datetime(2000, 10, 8, 0, 56, 40, tzinfo=datetime.timezone.utc),\n        ),\n    ],\n)\ndef test_datetime_headers(header, header_attr, header_val, expected) -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={header: header_val})\n    assert getattr(req, header_attr) == expected\n",
            "new_file_content": "import asyncio\nimport datetime\nimport socket\nfrom collections.abc import MutableMapping\nfrom typing import Any\nfrom unittest import mock\n\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy, MultiDict\nfrom yarl import URL\n\nfrom aiohttp import HttpVersion\nfrom aiohttp.http_parser import RawRequestMessage\nfrom aiohttp.streams import StreamReader\nfrom aiohttp.test_utils import make_mocked_request\nfrom aiohttp.web import BaseRequest, HTTPRequestEntityTooLarge\nfrom aiohttp.web_request import ETag\n\n\n@pytest.fixture\ndef protocol():\n    return mock.Mock(_reading_paused=False)\n\n\ndef test_base_ctor() -> None:\n    message = RawRequestMessage(\n        \"GET\",\n        \"/path/to?a=1&b=2\",\n        HttpVersion(1, 1),\n        CIMultiDictProxy(CIMultiDict()),\n        (),\n        False,\n        False,\n        False,\n        False,\n        URL(\"/path/to?a=1&b=2\"),\n    )\n\n    req = BaseRequest(\n        message, mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock()\n    )\n\n    assert \"GET\" == req.method\n    assert HttpVersion(1, 1) == req.version\n    # MacOS may return CamelCased host name, need .lower()\n    # FQDN can be wider than host, e.g.\n    # 'fv-az397-495' in 'fv-az397-495.internal.cloudapp.net'\n    assert req.host.lower() in socket.getfqdn().lower()\n    assert \"/path/to?a=1&b=2\" == req.path_qs\n    assert \"/path/to\" == req.path\n    assert \"a=1&b=2\" == req.query_string\n    assert CIMultiDict() == req.headers\n    assert () == req.raw_headers\n\n    get = req.query\n    assert MultiDict([(\"a\", \"1\"), (\"b\", \"2\")]) == get\n    # second call should return the same object\n    assert get is req.query\n\n    assert req.keep_alive\n\n    assert req\n\n\ndef test_ctor() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n\n    assert \"GET\" == req.method\n    assert HttpVersion(1, 1) == req.version\n    # MacOS may return CamelCased host name, need .lower()\n    # FQDN can be wider than host, e.g.\n    # 'fv-az397-495' in 'fv-az397-495.internal.cloudapp.net'\n    assert req.host.lower() in socket.getfqdn().lower()\n    assert \"/path/to?a=1&b=2\" == req.path_qs\n    assert \"/path/to\" == req.path\n    assert \"a=1&b=2\" == req.query_string\n    assert CIMultiDict() == req.headers\n    assert () == req.raw_headers\n\n    get = req.query\n    assert MultiDict([(\"a\", \"1\"), (\"b\", \"2\")]) == get\n    # second call should return the same object\n    assert get is req.query\n\n    assert req.keep_alive\n\n    # just make sure that all lines of make_mocked_request covered\n    headers = CIMultiDict(FOO=\"bar\")\n    payload = mock.Mock()\n    protocol = mock.Mock()\n    app = mock.Mock()\n    req = make_mocked_request(\n        \"GET\",\n        \"/path/to?a=1&b=2\",\n        headers=headers,\n        protocol=protocol,\n        payload=payload,\n        app=app,\n    )\n    assert req.app is app\n    assert req.content is payload\n    assert req.protocol is protocol\n    assert req.transport is protocol.transport\n    assert req.headers == headers\n    assert req.raw_headers == ((b\"FOO\", b\"bar\"),)\n    assert req.task is req._task\n\n\ndef test_deprecated_message() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    with pytest.deprecated_call(match=r\"^Request\\.message is deprecated$\"):\n        assert req.message == req._message\n\n\ndef test_doubleslashes() -> None:\n    # NB: //foo/bar is an absolute URL with foo netloc and /bar path\n    req = make_mocked_request(\"GET\", \"/bar//foo/\")\n    assert \"/bar//foo/\" == req.path\n\n\ndef test_content_type_not_specified() -> None:\n    req = make_mocked_request(\"Get\", \"/\")\n    assert \"application/octet-stream\" == req.content_type\n\n\ndef test_content_type_from_spec() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"application/json\")])\n    )\n    assert \"application/json\" == req.content_type\n\n\ndef test_content_type_from_spec_with_charset() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"text/html; charset=UTF-8\")])\n    )\n    assert \"text/html\" == req.content_type\n    assert \"UTF-8\" == req.charset\n\n\ndef test_calc_content_type_on_getting_charset() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"text/html; charset=UTF-8\")])\n    )\n    assert \"UTF-8\" == req.charset\n    assert \"text/html\" == req.content_type\n\n\ndef test_urlencoded_querystring() -> None:\n    req = make_mocked_request(\"GET\", \"/yandsearch?text=%D1%82%D0%B5%D0%BA%D1%81%D1%82\")\n    assert {\"text\": \"текст\"} == req.query\n\n\ndef test_non_ascii_path() -> None:\n    req = make_mocked_request(\"GET\", \"/путь\")\n    assert \"/путь\" == req.path\n\n\ndef test_non_ascii_raw_path() -> None:\n    req = make_mocked_request(\"GET\", \"/путь\")\n    assert \"/путь\" == req.raw_path\n\n\ndef test_absolute_url() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.url == URL(\"https://example.com/path/to?a=1\")\n    assert req.scheme == \"https\"\n    assert req.host == \"example.com\"\n    assert req.rel_url == URL.build(path=\"/path/to\", query={\"a\": \"1\"})\n\n\ndef test_clone_absolute_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.scheme == \"https\"\n    req2 = req.clone(scheme=\"http\")\n    assert req2.scheme == \"http\"\n    assert req2.url.scheme == \"http\"\n\n\ndef test_clone_absolute_host() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.host == \"example.com\"\n    req2 = req.clone(host=\"foo.test\")\n    assert req2.host == \"foo.test\"\n    assert req2.url.host == \"foo.test\"\n\n\ndef test_content_length() -> None:\n    req = make_mocked_request(\"Get\", \"/\", CIMultiDict([(\"CONTENT-LENGTH\", \"123\")]))\n\n    assert 123 == req.content_length\n\n\ndef test_range_to_slice_head() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=0-499\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[:500]\n\n\ndef test_range_to_slice_mid() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=500-999\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[500:1000]\n\n\ndef test_range_to_slice_tail_start() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=9500-\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[-500:]\n\n\ndef test_range_to_slice_tail_stop() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=-500\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[-500:]\n\n\ndef test_non_keepalive_on_http10() -> None:\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion(1, 0))\n    assert not req.keep_alive\n\n\ndef test_non_keepalive_on_closing() -> None:\n    req = make_mocked_request(\"GET\", \"/\", closing=True)\n    assert not req.keep_alive\n\n\nasync def test_call_POST_on_GET_request() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    ret = await req.post()\n    assert CIMultiDict() == ret\n\n\nasync def test_call_POST_on_weird_content_type() -> None:\n    req = make_mocked_request(\n        \"POST\", \"/\", headers=CIMultiDict({\"CONTENT-TYPE\": \"something/weird\"})\n    )\n\n    ret = await req.post()\n    assert CIMultiDict() == ret\n\n\nasync def test_call_POST_twice() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    ret1 = await req.post()\n    ret2 = await req.post()\n    assert ret1 is ret2\n\n\ndef test_no_request_cookies() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    assert req.cookies == {}\n\n    cookies = req.cookies\n    assert cookies is req.cookies\n\n\ndef test_request_cookie() -> None:\n    headers = CIMultiDict(COOKIE=\"cookie1=value1; cookie2=value2\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n\n    assert req.cookies == {\"cookie1\": \"value1\", \"cookie2\": \"value2\"}\n\n\ndef test_request_cookie__set_item() -> None:\n    headers = CIMultiDict(COOKIE=\"name=value\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n\n    assert req.cookies == {\"name\": \"value\"}\n\n    with pytest.raises(TypeError):\n        req.cookies[\"my\"] = \"value\"\n\n\ndef test_match_info() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req._match_info is req.match_info\n\n\ndef test_request_is_mutable_mapping() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert isinstance(req, MutableMapping)\n    req[\"key\"] = \"value\"\n    assert \"value\" == req[\"key\"]\n\n\ndef test_request_delitem() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"value\"\n    assert \"value\" == req[\"key\"]\n    del req[\"key\"]\n    assert \"key\" not in req\n\n\ndef test_request_len() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert len(req) == 0\n    req[\"key\"] = \"value\"\n    assert len(req) == 1\n\n\ndef test_request_iter() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"value\"\n    req[\"key2\"] = \"value2\"\n    assert set(req) == {\"key\", \"key2\"}\n\n\ndef test___repr__() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to\")\n    assert \"<Request GET /path/to >\" == repr(req)\n\n\ndef test___repr___non_ascii_path() -> None:\n    req = make_mocked_request(\"GET\", \"/path/\\U0001f415\\U0001f308\")\n    assert \"<Request GET /path/\\\\U0001f415\\\\U0001f308 >\" == repr(req)\n\n\ndef test_http_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={\"Host\": \"example.com\"})\n    assert \"http\" == req.scheme\n    assert req.secure is False\n\n\ndef test_https_scheme_by_ssl_transport() -> None:\n    req = make_mocked_request(\n        \"GET\", \"/\", headers={\"Host\": \"example.com\"}, sslcontext=True\n    )\n    assert \"https\" == req.scheme\n    assert req.secure is True\n\n\ndef test_single_forwarded_header() -> None:\n    header = \"by=identifier;for=identifier;host=identifier;proto=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"host\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"identifier\"\n\n\n@pytest.mark.parametrize(\n    \"forward_for_in, forward_for_out\",\n    [\n        (\"1.2.3.4:1234\", \"1.2.3.4:1234\"),\n        (\"1.2.3.4\", \"1.2.3.4\"),\n        ('\"[2001:db8:cafe::17]:1234\"', \"[2001:db8:cafe::17]:1234\"),\n        ('\"[2001:db8:cafe::17]\"', \"[2001:db8:cafe::17]\"),\n    ],\n)\ndef test_forwarded_node_identifier(forward_for_in, forward_for_out) -> None:\n    header = f\"for={forward_for_in}\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded == ({\"for\": forward_for_out},)\n\n\ndef test_single_forwarded_header_camelcase() -> None:\n    header = \"bY=identifier;fOr=identifier;HOst=identifier;pRoTO=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"host\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"identifier\"\n\n\ndef test_single_forwarded_header_single_param() -> None:\n    header = \"BY=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n\n\ndef test_single_forwarded_header_multiple_param() -> None:\n    header = \"By=identifier1,BY=identifier2,  By=identifier3 ,  BY=identifier4\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 4\n    assert req.forwarded[0][\"by\"] == \"identifier1\"\n    assert req.forwarded[1][\"by\"] == \"identifier2\"\n    assert req.forwarded[2][\"by\"] == \"identifier3\"\n    assert req.forwarded[3][\"by\"] == \"identifier4\"\n\n\ndef test_single_forwarded_header_quoted_escaped() -> None:\n    header = r'BY=identifier;pROTO=\"\\lala lan\\d\\~ 123\\!&\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"lala land~ 123!&\"\n\n\ndef test_single_forwarded_header_custom_param() -> None:\n    header = r'BY=identifier;PROTO=https;SOME=\"other, \\\"value\\\"\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 1\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"https\"\n    assert req.forwarded[0][\"some\"] == 'other, \"value\"'\n\n\ndef test_single_forwarded_header_empty_params() -> None:\n    # This is allowed by the grammar given in RFC 7239\n    header = \";For=identifier;;PROTO=https;;;\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"https\"\n\n\ndef test_single_forwarded_header_bad_separator() -> None:\n    header = \"BY=identifier PROTO=https\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert \"proto\" not in req.forwarded[0]\n\n\ndef test_single_forwarded_header_injection1() -> None:\n    # We might receive a header like this if we're sitting behind a reverse\n    # proxy that blindly appends a forwarded-element without checking\n    # the syntax of existing field-values. We should be able to recover\n    # the appended element anyway.\n    header = 'for=_injected;by=\", for=_real'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 2\n    assert \"by\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n\n\ndef test_single_forwarded_header_injection2() -> None:\n    header = \"very bad syntax, for=_real\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 2\n    assert \"for\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n\n\ndef test_single_forwarded_header_long_quoted_string() -> None:\n    header = 'for=\"' + \"\\\\\\\\\" * 5000 + '\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"for\"] == \"\\\\\" * 5000\n\n\ndef test_multiple_forwarded_headers() -> None:\n    headers = CIMultiDict()\n    headers.add(\"Forwarded\", \"By=identifier1;for=identifier2, BY=identifier3\")\n    headers.add(\"Forwarded\", \"By=identifier4;fOr=identifier5\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 3\n    assert req.forwarded[0][\"by\"] == \"identifier1\"\n    assert req.forwarded[0][\"for\"] == \"identifier2\"\n    assert req.forwarded[1][\"by\"] == \"identifier3\"\n    assert req.forwarded[2][\"by\"] == \"identifier4\"\n    assert req.forwarded[2][\"for\"] == \"identifier5\"\n\n\ndef test_multiple_forwarded_headers_bad_syntax() -> None:\n    headers = CIMultiDict()\n    headers.add(\"Forwarded\", \"for=_1;by=_2\")\n    headers.add(\"Forwarded\", \"invalid value\")\n    headers.add(\"Forwarded\", \"\")\n    headers.add(\"Forwarded\", \"for=_3;by=_4\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 4\n    assert req.forwarded[0][\"for\"] == \"_1\"\n    assert \"for\" not in req.forwarded[1]\n    assert \"for\" not in req.forwarded[2]\n    assert req.forwarded[3][\"by\"] == \"_4\"\n\n\ndef test_multiple_forwarded_headers_injection() -> None:\n    headers = CIMultiDict()\n    # This could be sent by an attacker, hoping to \"shadow\" the second header.\n    headers.add(\"Forwarded\", 'for=_injected;by=\"')\n    # This is added by our trusted reverse proxy.\n    headers.add(\"Forwarded\", \"for=_real;by=_actual_proxy\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 2\n    assert \"by\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n    assert req.forwarded[1][\"by\"] == \"_actual_proxy\"\n\n\ndef test_host_by_host_header() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Host\": \"example.com\"}))\n    assert req.host == \"example.com\"\n\n\ndef test_raw_headers() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"X-HEADER\": \"aaa\"}))\n    assert req.raw_headers == ((b\"X-HEADER\", b\"aaa\"),)\n\n\ndef test_rel_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    assert URL(\"/path\") == req.rel_url\n\n\ndef test_url_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"HOST\": \"example.com\"})\n    assert URL(\"http://example.com/path\") == req.url\n\n\ndef test_clone() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone()\n    assert req2.method == \"GET\"\n    assert req2.rel_url == URL(\"/path\")\n\n\ndef test_clone_client_max_size() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", client_max_size=1024)\n    req2 = req.clone()\n    assert req._client_max_size == req2._client_max_size\n    assert req2._client_max_size == 1024\n\n\ndef test_clone_override_client_max_size() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", client_max_size=1024)\n    req2 = req.clone(client_max_size=2048)\n    assert req2.client_max_size == 2048\n\n\ndef test_clone_method() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(method=\"POST\")\n    assert req2.method == \"POST\"\n    assert req2.rel_url == URL(\"/path\")\n\n\ndef test_clone_rel_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(rel_url=URL(\"/path2\"))\n    assert req2.rel_url == URL(\"/path2\")\n\n\ndef test_clone_rel_url_str() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(rel_url=\"/path2\")\n    assert req2.rel_url == URL(\"/path2\")\n\n\ndef test_clone_headers() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"A\": \"B\"})\n    req2 = req.clone(headers=CIMultiDict({\"B\": \"C\"}))\n    assert req2.headers == CIMultiDict({\"B\": \"C\"})\n    assert req2.raw_headers == ((b\"B\", b\"C\"),)\n\n\ndef test_clone_headers_dict() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"A\": \"B\"})\n    req2 = req.clone(headers={\"B\": \"C\"})\n    assert req2.headers == CIMultiDict({\"B\": \"C\"})\n    assert req2.raw_headers == ((b\"B\", b\"C\"),)\n\n\nasync def test_cannot_clone_after_read(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(b\"data\")\n    payload.feed_eof()\n    req = make_mocked_request(\"GET\", \"/path\", payload=payload)\n    await req.read()\n    with pytest.raises(RuntimeError):\n        req.clone()\n\n\nasync def test_make_too_big_request(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    req = make_mocked_request(\"POST\", \"/\", payload=payload)\n    with pytest.raises(HTTPRequestEntityTooLarge) as err:\n        await req.read()\n\n    assert err.value.status_code == 413\n\n\nasync def test_make_too_big_request_adjust_limit(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    max_size = 1024**2 + 2\n    req = make_mocked_request(\"POST\", \"/\", payload=payload, client_max_size=max_size)\n    txt = await req.read()\n    assert len(txt) == 1024**2 + 1\n\n\nasync def test_multipart_formdata(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"a\"\\r\\n'\n        b\"\\r\\n\"\n        b\"b\\r\\n\"\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"c\"\\r\\n'\n        b\"\\r\\n\"\n        b\"d\\r\\n\"\n        b\"-----------------------------326931944431359--\\r\\n\"\n    )\n    content_type = (\n        \"multipart/form-data; boundary=\" \"---------------------------326931944431359\"\n    )\n    payload.feed_eof()\n    req = make_mocked_request(\n        \"POST\", \"/\", headers={\"CONTENT-TYPE\": content_type}, payload=payload\n    )\n    result = await req.post()\n    assert dict(result) == {\"a\": \"b\", \"c\": \"d\"}\n\n\nasync def test_multipart_formdata_file(protocol) -> None:\n    # Make sure file uploads work, even without a content type\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"a_file\"; filename=\"binary\"\\r\\n'\n        b\"\\r\\n\"\n        b\"\\ff\\r\\n\"\n        b\"-----------------------------326931944431359--\\r\\n\"\n    )\n    content_type = (\n        \"multipart/form-data; boundary=\" \"---------------------------326931944431359\"\n    )\n    payload.feed_eof()\n    req = make_mocked_request(\n        \"POST\", \"/\", headers={\"CONTENT-TYPE\": content_type}, payload=payload\n    )\n    result = await req.post()\n    assert hasattr(result[\"a_file\"], \"file\")\n    content = result[\"a_file\"].file.read()\n    assert content == b\"\\ff\"\n\n    result[\"a_file\"].file.close()\n\n\nasync def test_make_too_big_request_limit_None(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    max_size = None\n    req = make_mocked_request(\"POST\", \"/\", payload=payload, client_max_size=max_size)\n    txt = await req.read()\n    assert len(txt) == 1024**2 + 1\n\n\ndef test_remote_peername_tcp() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = (\"10.10.10.10\", 1234)\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    assert req.remote == \"10.10.10.10\"\n\n\ndef test_remote_peername_unix() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = \"/path/to/sock\"\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    assert req.remote == \"/path/to/sock\"\n\n\ndef test_save_state_on_clone() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"val\"\n    req2 = req.clone()\n    req2[\"key\"] = \"val2\"\n    assert req[\"key\"] == \"val\"\n    assert req2[\"key\"] == \"val2\"\n\n\ndef test_clone_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.scheme == \"http\"\n    req2 = req.clone(scheme=\"https\")\n    assert req2.scheme == \"https\"\n    assert req2.url.scheme == \"https\"\n\n\ndef test_clone_host() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.host != \"example.com\"\n    req2 = req.clone(host=\"example.com\")\n    assert req2.host == \"example.com\"\n    assert req2.url.host == \"example.com\"\n\n\ndef test_clone_remote() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.remote != \"11.11.11.11\"\n    req2 = req.clone(remote=\"11.11.11.11\")\n    assert req2.remote == \"11.11.11.11\"\n\n\ndef test_remote_with_closed_transport() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = (\"10.10.10.10\", 1234)\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    req._protocol = None\n    assert req.remote == \"10.10.10.10\"\n\n\ndef test_url_http_with_closed_transport() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req._protocol = None\n    assert str(req.url).startswith(\"http://\")\n\n\ndef test_url_https_with_closed_transport() -> None:\n    req = make_mocked_request(\"GET\", \"/\", sslcontext=True)\n    req._protocol = None\n    assert str(req.url).startswith(\"https://\")\n\n\nasync def test_get_extra_info() -> None:\n    valid_key = \"test\"\n    valid_value = \"existent\"\n    default_value = \"default\"\n\n    def get_extra_info(name: str, default: Any = None):\n        return {valid_key: valid_value}.get(name, default)\n\n    transp = mock.Mock()\n    transp.get_extra_info.side_effect = get_extra_info\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n\n    req_extra_info = req.get_extra_info(valid_key, default_value)\n    transp_extra_info = req._protocol.transport.get_extra_info(valid_key, default_value)\n    assert req_extra_info == transp_extra_info\n\n    req._protocol.transport = None\n    extra_info = req.get_extra_info(valid_key, default_value)\n    assert extra_info == default_value\n\n    req._protocol = None\n    extra_info = req.get_extra_info(valid_key, default_value)\n    assert extra_info == default_value\n\n\ndef test_eq() -> None:\n    req1 = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    req2 = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    assert req1 != req2\n    assert req1 == req1\n\n\nasync def test_loop_prop() -> None:\n    loop = asyncio.get_event_loop()\n    req = make_mocked_request(\"GET\", \"/path\", loop=loop)\n    with pytest.deprecated_call(match=r\"^request\\.loop property is deprecated$\"):\n        assert req.loop is loop\n\n\n@pytest.mark.parametrize(\n    [\"header\", \"header_attr\"],\n    [\n        pytest.param(\"If-Match\", \"if_match\"),\n        pytest.param(\"If-None-Match\", \"if_none_match\"),\n    ],\n)\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\n            '\"67ab43\", W/\"54ed21\", \"7892,dd\"',\n            (\n                ETag(is_weak=False, value=\"67ab43\"),\n                ETag(is_weak=True, value=\"54ed21\"),\n                ETag(is_weak=False, value=\"7892,dd\"),\n            ),\n        ),\n        pytest.param(\n            '\"bfc1ef-5b2c2730249c88ca92d82d\"',\n            (ETag(is_weak=False, value=\"bfc1ef-5b2c2730249c88ca92d82d\"),),\n        ),\n        pytest.param(\n            '\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"',\n            (\n                ETag(is_weak=False, value=\"valid-tag\"),\n                ETag(is_weak=False, value=\"also-valid-tag\"),\n            ),\n        ),\n        pytest.param(\n            '\"ascii\", \"это точно не ascii\", \"ascii again\"',\n            (ETag(is_weak=False, value=\"ascii\"),),\n        ),\n        pytest.param(\n            \"*\",\n            (ETag(is_weak=False, value=\"*\"),),\n        ),\n    ],\n)\ndef test_etag_headers(header, header_attr, header_val, expected) -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={header: header_val})\n    assert getattr(req, header_attr) == expected\n\n\n@pytest.mark.parametrize(\n    [\"header\", \"header_attr\"],\n    [\n        pytest.param(\"If-Modified-Since\", \"if_modified_since\"),\n        pytest.param(\"If-Unmodified-Since\", \"if_unmodified_since\"),\n        pytest.param(\"If-Range\", \"if_range\"),\n    ],\n)\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\"xxyyzz\", None),\n        pytest.param(\"Tue, 08 Oct 4446413 00:56:40 GMT\", None),\n        pytest.param(\"Tue, 08 Oct 2000 00:56:80 GMT\", None),\n        pytest.param(\n            \"Tue, 08 Oct 2000 00:56:40 GMT\",\n            datetime.datetime(2000, 10, 8, 0, 56, 40, tzinfo=datetime.timezone.utc),\n        ),\n    ],\n)\ndef test_datetime_headers(header, header_attr, header_val, expected) -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={header: header_val})\n    assert getattr(req, header_attr) == expected\n",
            "header": {
                "file": {
                    "path": "tests/test_web_request.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "c6398ac1",
                "new_commit_hash": "ba12d6f5",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_web_request.py"
            },
            "plus_file": {
                "path": "b/tests/test_web_request.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 169,
                            "length": 6
                        },
                        "new_range": {
                            "start": 169,
                            "length": 22
                        },
                        "section": "def test_absolute_url() -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    assert req.rel_url == URL.build(path=\"/path/to\", query={\"a\": \"1\"})",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_clone_absolute_scheme() -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")",
                                "type": "added"
                            },
                            {
                                "content": "    assert req.scheme == \"https\"",
                                "type": "added"
                            },
                            {
                                "content": "    req2 = req.clone(scheme=\"http\")",
                                "type": "added"
                            },
                            {
                                "content": "    assert req2.scheme == \"http\"",
                                "type": "added"
                            },
                            {
                                "content": "    assert req2.url.scheme == \"http\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "def test_clone_absolute_host() -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")",
                                "type": "added"
                            },
                            {
                                "content": "    assert req.host == \"example.com\"",
                                "type": "added"
                            },
                            {
                                "content": "    req2 = req.clone(host=\"foo.test\")",
                                "type": "added"
                            },
                            {
                                "content": "    assert req2.host == \"foo.test\"",
                                "type": "added"
                            },
                            {
                                "content": "    assert req2.url.host == \"foo.test\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "def test_content_length() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    req = make_mocked_request(\"Get\", \"/\", CIMultiDict([(\"CONTENT-LENGTH\", \"123\")]))",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tests/test_web_request.py",
                            "type": "function",
                            "name": "test_clone_absolute_host",
                            "content": "def test_clone_absolute_host() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.host == \"example.com\"\n    req2 = req.clone(host=\"foo.test\")\n    assert req2.host == \"foo.test\"\n    assert req2.url.host == \"foo.test\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 180,
                            "end_lineno": 185,
                            "parent": null
                        },
                        {
                            "file_name": "tests/test_web_request.py",
                            "type": "function",
                            "name": "test_clone_absolute_scheme",
                            "content": "def test_clone_absolute_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.scheme == \"https\"\n    req2 = req.clone(scheme=\"http\")\n    assert req2.scheme == \"http\"\n    assert req2.url.scheme == \"http\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 172,
                            "end_lineno": 177,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 684,
                            "length": 18
                        },
                        "new_range": {
                            "start": 700,
                            "length": 23
                        },
                        "section": "def test_save_state_on_clone() -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_clone_scheme() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    req = make_mocked_request(\"GET\", \"/\")",
                                "type": "context"
                            },
                            {
                                "content": "    assert req.scheme == \"http\"",
                                "type": "added"
                            },
                            {
                                "content": "    req2 = req.clone(scheme=\"https\")",
                                "type": "context"
                            },
                            {
                                "content": "    assert req2.scheme == \"https\"",
                                "type": "context"
                            },
                            {
                                "content": "    assert req2.url.scheme == \"https\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_clone_host() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    req = make_mocked_request(\"GET\", \"/\")",
                                "type": "context"
                            },
                            {
                                "content": "    assert req.host != \"example.com\"",
                                "type": "added"
                            },
                            {
                                "content": "    req2 = req.clone(host=\"example.com\")",
                                "type": "context"
                            },
                            {
                                "content": "    assert req2.host == \"example.com\"",
                                "type": "context"
                            },
                            {
                                "content": "    assert req2.url.host == \"example.com\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_clone_remote() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    req = make_mocked_request(\"GET\", \"/\")",
                                "type": "context"
                            },
                            {
                                "content": "    assert req.remote != \"11.11.11.11\"",
                                "type": "added"
                            },
                            {
                                "content": "    req2 = req.clone(remote=\"11.11.11.11\")",
                                "type": "context"
                            },
                            {
                                "content": "    assert req2.remote == \"11.11.11.11\"",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_web_request.py",
                            "type": "function",
                            "name": "test_clone_remote",
                            "content": "def test_clone_remote() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.remote != \"11.11.11.11\"\n    req2 = req.clone(remote=\"11.11.11.11\")\n    assert req2.remote == \"11.11.11.11\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 717,
                            "end_lineno": 721,
                            "parent": null
                        },
                        {
                            "file_name": "tests/test_web_request.py",
                            "type": "function",
                            "name": "test_clone_host",
                            "content": "def test_clone_host() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.host != \"example.com\"\n    req2 = req.clone(host=\"example.com\")\n    assert req2.host == \"example.com\"\n    assert req2.url.host == \"example.com\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 709,
                            "end_lineno": 714,
                            "parent": null
                        },
                        {
                            "file_name": "tests/test_web_request.py",
                            "type": "function",
                            "name": "test_clone_scheme",
                            "content": "def test_clone_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.scheme == \"http\"\n    req2 = req.clone(scheme=\"https\")\n    assert req2.scheme == \"https\"\n    assert req2.url.scheme == \"https\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 701,
                            "end_lineno": 706,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "fa628a2170cc03b82f32ea4e3812f41d015125e3^",
    "new_commit_hash": "fa628a2170cc03b82f32ea4e3812f41d015125e3",
    "commit_message": "[PR #8990/731ba4dd backport][3.11] Fix changing scheme/host in Response.clone() for absolute URLs (#8997)\n\n**This is a backport of PR #8990 as merged into master\r\n(731ba4dd399c26fd470dde5ea50e011e058b798a).**\r\n\r\nCo-authored-by: Sam Bull <git@sambull.org>",
    "commit_date": "2024-09-03T00:49:45+01:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "fa628a2170cc03b82f32ea4e3812f41d015125e3",
    "test_file_codes": [
        "import asyncio\nimport datetime\nimport socket\nfrom collections.abc import MutableMapping\nfrom typing import Any\nfrom unittest import mock\n\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy, MultiDict\nfrom yarl import URL\n\nfrom aiohttp import HttpVersion\nfrom aiohttp.http_parser import RawRequestMessage\nfrom aiohttp.streams import StreamReader\nfrom aiohttp.test_utils import make_mocked_request\nfrom aiohttp.web import BaseRequest, HTTPRequestEntityTooLarge\nfrom aiohttp.web_request import ETag\n\n\n@pytest.fixture\ndef protocol():\n    return mock.Mock(_reading_paused=False)\n\n\ndef test_base_ctor() -> None:\n    message = RawRequestMessage(\n        \"GET\",\n        \"/path/to?a=1&b=2\",\n        HttpVersion(1, 1),\n        CIMultiDictProxy(CIMultiDict()),\n        (),\n        False,\n        False,\n        False,\n        False,\n        URL(\"/path/to?a=1&b=2\"),\n    )\n\n    req = BaseRequest(\n        message, mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock()\n    )\n\n    assert \"GET\" == req.method\n    assert HttpVersion(1, 1) == req.version\n    # MacOS may return CamelCased host name, need .lower()\n    # FQDN can be wider than host, e.g.\n    # 'fv-az397-495' in 'fv-az397-495.internal.cloudapp.net'\n    assert req.host.lower() in socket.getfqdn().lower()\n    assert \"/path/to?a=1&b=2\" == req.path_qs\n    assert \"/path/to\" == req.path\n    assert \"a=1&b=2\" == req.query_string\n    assert CIMultiDict() == req.headers\n    assert () == req.raw_headers\n\n    get = req.query\n    assert MultiDict([(\"a\", \"1\"), (\"b\", \"2\")]) == get\n    # second call should return the same object\n    assert get is req.query\n\n    assert req.keep_alive\n\n    assert req\n\n\ndef test_ctor() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n\n    assert \"GET\" == req.method\n    assert HttpVersion(1, 1) == req.version\n    # MacOS may return CamelCased host name, need .lower()\n    # FQDN can be wider than host, e.g.\n    # 'fv-az397-495' in 'fv-az397-495.internal.cloudapp.net'\n    assert req.host.lower() in socket.getfqdn().lower()\n    assert \"/path/to?a=1&b=2\" == req.path_qs\n    assert \"/path/to\" == req.path\n    assert \"a=1&b=2\" == req.query_string\n    assert CIMultiDict() == req.headers\n    assert () == req.raw_headers\n\n    get = req.query\n    assert MultiDict([(\"a\", \"1\"), (\"b\", \"2\")]) == get\n    # second call should return the same object\n    assert get is req.query\n\n    assert req.keep_alive\n\n    # just make sure that all lines of make_mocked_request covered\n    headers = CIMultiDict(FOO=\"bar\")\n    payload = mock.Mock()\n    protocol = mock.Mock()\n    app = mock.Mock()\n    req = make_mocked_request(\n        \"GET\",\n        \"/path/to?a=1&b=2\",\n        headers=headers,\n        protocol=protocol,\n        payload=payload,\n        app=app,\n    )\n    assert req.app is app\n    assert req.content is payload\n    assert req.protocol is protocol\n    assert req.transport is protocol.transport\n    assert req.headers == headers\n    assert req.raw_headers == ((b\"FOO\", b\"bar\"),)\n    assert req.task is req._task\n\n\ndef test_deprecated_message() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    with pytest.deprecated_call(match=r\"^Request\\.message is deprecated$\"):\n        assert req.message == req._message\n\n\ndef test_doubleslashes() -> None:\n    # NB: //foo/bar is an absolute URL with foo netloc and /bar path\n    req = make_mocked_request(\"GET\", \"/bar//foo/\")\n    assert \"/bar//foo/\" == req.path\n\n\ndef test_content_type_not_specified() -> None:\n    req = make_mocked_request(\"Get\", \"/\")\n    assert \"application/octet-stream\" == req.content_type\n\n\ndef test_content_type_from_spec() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"application/json\")])\n    )\n    assert \"application/json\" == req.content_type\n\n\ndef test_content_type_from_spec_with_charset() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"text/html; charset=UTF-8\")])\n    )\n    assert \"text/html\" == req.content_type\n    assert \"UTF-8\" == req.charset\n\n\ndef test_calc_content_type_on_getting_charset() -> None:\n    req = make_mocked_request(\n        \"Get\", \"/\", CIMultiDict([(\"CONTENT-TYPE\", \"text/html; charset=UTF-8\")])\n    )\n    assert \"UTF-8\" == req.charset\n    assert \"text/html\" == req.content_type\n\n\ndef test_urlencoded_querystring() -> None:\n    req = make_mocked_request(\"GET\", \"/yandsearch?text=%D1%82%D0%B5%D0%BA%D1%81%D1%82\")\n    assert {\"text\": \"текст\"} == req.query\n\n\ndef test_non_ascii_path() -> None:\n    req = make_mocked_request(\"GET\", \"/путь\")\n    assert \"/путь\" == req.path\n\n\ndef test_non_ascii_raw_path() -> None:\n    req = make_mocked_request(\"GET\", \"/путь\")\n    assert \"/путь\" == req.raw_path\n\n\ndef test_absolute_url() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.url == URL(\"https://example.com/path/to?a=1\")\n    assert req.scheme == \"https\"\n    assert req.host == \"example.com\"\n    assert req.rel_url == URL.build(path=\"/path/to\", query={\"a\": \"1\"})\n\n\ndef test_clone_absolute_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.scheme == \"https\"\n    req2 = req.clone(scheme=\"http\")\n    assert req2.scheme == \"http\"\n    assert req2.url.scheme == \"http\"\n\n\ndef test_clone_absolute_host() -> None:\n    req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n    assert req.host == \"example.com\"\n    req2 = req.clone(host=\"foo.test\")\n    assert req2.host == \"foo.test\"\n    assert req2.url.host == \"foo.test\"\n\n\ndef test_content_length() -> None:\n    req = make_mocked_request(\"Get\", \"/\", CIMultiDict([(\"CONTENT-LENGTH\", \"123\")]))\n\n    assert 123 == req.content_length\n\n\ndef test_range_to_slice_head() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=0-499\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[:500]\n\n\ndef test_range_to_slice_mid() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=500-999\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[500:1000]\n\n\ndef test_range_to_slice_tail_start() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=9500-\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[-500:]\n\n\ndef test_range_to_slice_tail_stop() -> None:\n    def bytes_gen(size):\n        for i in range(size):\n            yield i % 256\n\n    payload = bytearray(bytes_gen(10000))\n    req = make_mocked_request(\n        \"GET\", \"/\", headers=CIMultiDict([(\"RANGE\", \"bytes=-500\")]), payload=payload\n    )\n    assert isinstance(req.http_range, slice)\n    assert req.content[req.http_range] == payload[-500:]\n\n\ndef test_non_keepalive_on_http10() -> None:\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion(1, 0))\n    assert not req.keep_alive\n\n\ndef test_non_keepalive_on_closing() -> None:\n    req = make_mocked_request(\"GET\", \"/\", closing=True)\n    assert not req.keep_alive\n\n\nasync def test_call_POST_on_GET_request() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    ret = await req.post()\n    assert CIMultiDict() == ret\n\n\nasync def test_call_POST_on_weird_content_type() -> None:\n    req = make_mocked_request(\n        \"POST\", \"/\", headers=CIMultiDict({\"CONTENT-TYPE\": \"something/weird\"})\n    )\n\n    ret = await req.post()\n    assert CIMultiDict() == ret\n\n\nasync def test_call_POST_twice() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    ret1 = await req.post()\n    ret2 = await req.post()\n    assert ret1 is ret2\n\n\ndef test_no_request_cookies() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n\n    assert req.cookies == {}\n\n    cookies = req.cookies\n    assert cookies is req.cookies\n\n\ndef test_request_cookie() -> None:\n    headers = CIMultiDict(COOKIE=\"cookie1=value1; cookie2=value2\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n\n    assert req.cookies == {\"cookie1\": \"value1\", \"cookie2\": \"value2\"}\n\n\ndef test_request_cookie__set_item() -> None:\n    headers = CIMultiDict(COOKIE=\"name=value\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n\n    assert req.cookies == {\"name\": \"value\"}\n\n    with pytest.raises(TypeError):\n        req.cookies[\"my\"] = \"value\"\n\n\ndef test_match_info() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req._match_info is req.match_info\n\n\ndef test_request_is_mutable_mapping() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert isinstance(req, MutableMapping)\n    req[\"key\"] = \"value\"\n    assert \"value\" == req[\"key\"]\n\n\ndef test_request_delitem() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"value\"\n    assert \"value\" == req[\"key\"]\n    del req[\"key\"]\n    assert \"key\" not in req\n\n\ndef test_request_len() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert len(req) == 0\n    req[\"key\"] = \"value\"\n    assert len(req) == 1\n\n\ndef test_request_iter() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"value\"\n    req[\"key2\"] = \"value2\"\n    assert set(req) == {\"key\", \"key2\"}\n\n\ndef test___repr__() -> None:\n    req = make_mocked_request(\"GET\", \"/path/to\")\n    assert \"<Request GET /path/to >\" == repr(req)\n\n\ndef test___repr___non_ascii_path() -> None:\n    req = make_mocked_request(\"GET\", \"/path/\\U0001f415\\U0001f308\")\n    assert \"<Request GET /path/\\\\U0001f415\\\\U0001f308 >\" == repr(req)\n\n\ndef test_http_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={\"Host\": \"example.com\"})\n    assert \"http\" == req.scheme\n    assert req.secure is False\n\n\ndef test_https_scheme_by_ssl_transport() -> None:\n    req = make_mocked_request(\n        \"GET\", \"/\", headers={\"Host\": \"example.com\"}, sslcontext=True\n    )\n    assert \"https\" == req.scheme\n    assert req.secure is True\n\n\ndef test_single_forwarded_header() -> None:\n    header = \"by=identifier;for=identifier;host=identifier;proto=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"host\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"identifier\"\n\n\n@pytest.mark.parametrize(\n    \"forward_for_in, forward_for_out\",\n    [\n        (\"1.2.3.4:1234\", \"1.2.3.4:1234\"),\n        (\"1.2.3.4\", \"1.2.3.4\"),\n        ('\"[2001:db8:cafe::17]:1234\"', \"[2001:db8:cafe::17]:1234\"),\n        ('\"[2001:db8:cafe::17]\"', \"[2001:db8:cafe::17]\"),\n    ],\n)\ndef test_forwarded_node_identifier(forward_for_in, forward_for_out) -> None:\n    header = f\"for={forward_for_in}\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded == ({\"for\": forward_for_out},)\n\n\ndef test_single_forwarded_header_camelcase() -> None:\n    header = \"bY=identifier;fOr=identifier;HOst=identifier;pRoTO=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"host\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"identifier\"\n\n\ndef test_single_forwarded_header_single_param() -> None:\n    header = \"BY=identifier\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n\n\ndef test_single_forwarded_header_multiple_param() -> None:\n    header = \"By=identifier1,BY=identifier2,  By=identifier3 ,  BY=identifier4\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 4\n    assert req.forwarded[0][\"by\"] == \"identifier1\"\n    assert req.forwarded[1][\"by\"] == \"identifier2\"\n    assert req.forwarded[2][\"by\"] == \"identifier3\"\n    assert req.forwarded[3][\"by\"] == \"identifier4\"\n\n\ndef test_single_forwarded_header_quoted_escaped() -> None:\n    header = r'BY=identifier;pROTO=\"\\lala lan\\d\\~ 123\\!&\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"lala land~ 123!&\"\n\n\ndef test_single_forwarded_header_custom_param() -> None:\n    header = r'BY=identifier;PROTO=https;SOME=\"other, \\\"value\\\"\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 1\n    assert req.forwarded[0][\"by\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"https\"\n    assert req.forwarded[0][\"some\"] == 'other, \"value\"'\n\n\ndef test_single_forwarded_header_empty_params() -> None:\n    # This is allowed by the grammar given in RFC 7239\n    header = \";For=identifier;;PROTO=https;;;\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"for\"] == \"identifier\"\n    assert req.forwarded[0][\"proto\"] == \"https\"\n\n\ndef test_single_forwarded_header_bad_separator() -> None:\n    header = \"BY=identifier PROTO=https\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert \"proto\" not in req.forwarded[0]\n\n\ndef test_single_forwarded_header_injection1() -> None:\n    # We might receive a header like this if we're sitting behind a reverse\n    # proxy that blindly appends a forwarded-element without checking\n    # the syntax of existing field-values. We should be able to recover\n    # the appended element anyway.\n    header = 'for=_injected;by=\", for=_real'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 2\n    assert \"by\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n\n\ndef test_single_forwarded_header_injection2() -> None:\n    header = \"very bad syntax, for=_real\"\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert len(req.forwarded) == 2\n    assert \"for\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n\n\ndef test_single_forwarded_header_long_quoted_string() -> None:\n    header = 'for=\"' + \"\\\\\\\\\" * 5000 + '\"'\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Forwarded\": header}))\n    assert req.forwarded[0][\"for\"] == \"\\\\\" * 5000\n\n\ndef test_multiple_forwarded_headers() -> None:\n    headers = CIMultiDict()\n    headers.add(\"Forwarded\", \"By=identifier1;for=identifier2, BY=identifier3\")\n    headers.add(\"Forwarded\", \"By=identifier4;fOr=identifier5\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 3\n    assert req.forwarded[0][\"by\"] == \"identifier1\"\n    assert req.forwarded[0][\"for\"] == \"identifier2\"\n    assert req.forwarded[1][\"by\"] == \"identifier3\"\n    assert req.forwarded[2][\"by\"] == \"identifier4\"\n    assert req.forwarded[2][\"for\"] == \"identifier5\"\n\n\ndef test_multiple_forwarded_headers_bad_syntax() -> None:\n    headers = CIMultiDict()\n    headers.add(\"Forwarded\", \"for=_1;by=_2\")\n    headers.add(\"Forwarded\", \"invalid value\")\n    headers.add(\"Forwarded\", \"\")\n    headers.add(\"Forwarded\", \"for=_3;by=_4\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 4\n    assert req.forwarded[0][\"for\"] == \"_1\"\n    assert \"for\" not in req.forwarded[1]\n    assert \"for\" not in req.forwarded[2]\n    assert req.forwarded[3][\"by\"] == \"_4\"\n\n\ndef test_multiple_forwarded_headers_injection() -> None:\n    headers = CIMultiDict()\n    # This could be sent by an attacker, hoping to \"shadow\" the second header.\n    headers.add(\"Forwarded\", 'for=_injected;by=\"')\n    # This is added by our trusted reverse proxy.\n    headers.add(\"Forwarded\", \"for=_real;by=_actual_proxy\")\n    req = make_mocked_request(\"GET\", \"/\", headers=headers)\n    assert len(req.forwarded) == 2\n    assert \"by\" not in req.forwarded[0]\n    assert req.forwarded[1][\"for\"] == \"_real\"\n    assert req.forwarded[1][\"by\"] == \"_actual_proxy\"\n\n\ndef test_host_by_host_header() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"Host\": \"example.com\"}))\n    assert req.host == \"example.com\"\n\n\ndef test_raw_headers() -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers=CIMultiDict({\"X-HEADER\": \"aaa\"}))\n    assert req.raw_headers == ((b\"X-HEADER\", b\"aaa\"),)\n\n\ndef test_rel_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    assert URL(\"/path\") == req.rel_url\n\n\ndef test_url_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"HOST\": \"example.com\"})\n    assert URL(\"http://example.com/path\") == req.url\n\n\ndef test_clone() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone()\n    assert req2.method == \"GET\"\n    assert req2.rel_url == URL(\"/path\")\n\n\ndef test_clone_client_max_size() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", client_max_size=1024)\n    req2 = req.clone()\n    assert req._client_max_size == req2._client_max_size\n    assert req2._client_max_size == 1024\n\n\ndef test_clone_override_client_max_size() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", client_max_size=1024)\n    req2 = req.clone(client_max_size=2048)\n    assert req2.client_max_size == 2048\n\n\ndef test_clone_method() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(method=\"POST\")\n    assert req2.method == \"POST\"\n    assert req2.rel_url == URL(\"/path\")\n\n\ndef test_clone_rel_url() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(rel_url=URL(\"/path2\"))\n    assert req2.rel_url == URL(\"/path2\")\n\n\ndef test_clone_rel_url_str() -> None:\n    req = make_mocked_request(\"GET\", \"/path\")\n    req2 = req.clone(rel_url=\"/path2\")\n    assert req2.rel_url == URL(\"/path2\")\n\n\ndef test_clone_headers() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"A\": \"B\"})\n    req2 = req.clone(headers=CIMultiDict({\"B\": \"C\"}))\n    assert req2.headers == CIMultiDict({\"B\": \"C\"})\n    assert req2.raw_headers == ((b\"B\", b\"C\"),)\n\n\ndef test_clone_headers_dict() -> None:\n    req = make_mocked_request(\"GET\", \"/path\", headers={\"A\": \"B\"})\n    req2 = req.clone(headers={\"B\": \"C\"})\n    assert req2.headers == CIMultiDict({\"B\": \"C\"})\n    assert req2.raw_headers == ((b\"B\", b\"C\"),)\n\n\nasync def test_cannot_clone_after_read(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(b\"data\")\n    payload.feed_eof()\n    req = make_mocked_request(\"GET\", \"/path\", payload=payload)\n    await req.read()\n    with pytest.raises(RuntimeError):\n        req.clone()\n\n\nasync def test_make_too_big_request(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    req = make_mocked_request(\"POST\", \"/\", payload=payload)\n    with pytest.raises(HTTPRequestEntityTooLarge) as err:\n        await req.read()\n\n    assert err.value.status_code == 413\n\n\nasync def test_make_too_big_request_adjust_limit(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    max_size = 1024**2 + 2\n    req = make_mocked_request(\"POST\", \"/\", payload=payload, client_max_size=max_size)\n    txt = await req.read()\n    assert len(txt) == 1024**2 + 1\n\n\nasync def test_multipart_formdata(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"a\"\\r\\n'\n        b\"\\r\\n\"\n        b\"b\\r\\n\"\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"c\"\\r\\n'\n        b\"\\r\\n\"\n        b\"d\\r\\n\"\n        b\"-----------------------------326931944431359--\\r\\n\"\n    )\n    content_type = (\n        \"multipart/form-data; boundary=\" \"---------------------------326931944431359\"\n    )\n    payload.feed_eof()\n    req = make_mocked_request(\n        \"POST\", \"/\", headers={\"CONTENT-TYPE\": content_type}, payload=payload\n    )\n    result = await req.post()\n    assert dict(result) == {\"a\": \"b\", \"c\": \"d\"}\n\n\nasync def test_multipart_formdata_file(protocol) -> None:\n    # Make sure file uploads work, even without a content type\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    payload.feed_data(\n        b\"-----------------------------326931944431359\\r\\n\"\n        b'Content-Disposition: form-data; name=\"a_file\"; filename=\"binary\"\\r\\n'\n        b\"\\r\\n\"\n        b\"\\ff\\r\\n\"\n        b\"-----------------------------326931944431359--\\r\\n\"\n    )\n    content_type = (\n        \"multipart/form-data; boundary=\" \"---------------------------326931944431359\"\n    )\n    payload.feed_eof()\n    req = make_mocked_request(\n        \"POST\", \"/\", headers={\"CONTENT-TYPE\": content_type}, payload=payload\n    )\n    result = await req.post()\n    assert hasattr(result[\"a_file\"], \"file\")\n    content = result[\"a_file\"].file.read()\n    assert content == b\"\\ff\"\n\n    result[\"a_file\"].file.close()\n\n\nasync def test_make_too_big_request_limit_None(protocol) -> None:\n    payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop())\n    large_file = 1024**2 * b\"x\"\n    too_large_file = large_file + b\"x\"\n    payload.feed_data(too_large_file)\n    payload.feed_eof()\n    max_size = None\n    req = make_mocked_request(\"POST\", \"/\", payload=payload, client_max_size=max_size)\n    txt = await req.read()\n    assert len(txt) == 1024**2 + 1\n\n\ndef test_remote_peername_tcp() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = (\"10.10.10.10\", 1234)\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    assert req.remote == \"10.10.10.10\"\n\n\ndef test_remote_peername_unix() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = \"/path/to/sock\"\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    assert req.remote == \"/path/to/sock\"\n\n\ndef test_save_state_on_clone() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req[\"key\"] = \"val\"\n    req2 = req.clone()\n    req2[\"key\"] = \"val2\"\n    assert req[\"key\"] == \"val\"\n    assert req2[\"key\"] == \"val2\"\n\n\ndef test_clone_scheme() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.scheme == \"http\"\n    req2 = req.clone(scheme=\"https\")\n    assert req2.scheme == \"https\"\n    assert req2.url.scheme == \"https\"\n\n\ndef test_clone_host() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.host != \"example.com\"\n    req2 = req.clone(host=\"example.com\")\n    assert req2.host == \"example.com\"\n    assert req2.url.host == \"example.com\"\n\n\ndef test_clone_remote() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    assert req.remote != \"11.11.11.11\"\n    req2 = req.clone(remote=\"11.11.11.11\")\n    assert req2.remote == \"11.11.11.11\"\n\n\ndef test_remote_with_closed_transport() -> None:\n    transp = mock.Mock()\n    transp.get_extra_info.return_value = (\"10.10.10.10\", 1234)\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n    req._protocol = None\n    assert req.remote == \"10.10.10.10\"\n\n\ndef test_url_http_with_closed_transport() -> None:\n    req = make_mocked_request(\"GET\", \"/\")\n    req._protocol = None\n    assert str(req.url).startswith(\"http://\")\n\n\ndef test_url_https_with_closed_transport() -> None:\n    req = make_mocked_request(\"GET\", \"/\", sslcontext=True)\n    req._protocol = None\n    assert str(req.url).startswith(\"https://\")\n\n\nasync def test_get_extra_info() -> None:\n    valid_key = \"test\"\n    valid_value = \"existent\"\n    default_value = \"default\"\n\n    def get_extra_info(name: str, default: Any = None):\n        return {valid_key: valid_value}.get(name, default)\n\n    transp = mock.Mock()\n    transp.get_extra_info.side_effect = get_extra_info\n    req = make_mocked_request(\"GET\", \"/\", transport=transp)\n\n    req_extra_info = req.get_extra_info(valid_key, default_value)\n    transp_extra_info = req._protocol.transport.get_extra_info(valid_key, default_value)\n    assert req_extra_info == transp_extra_info\n\n    req._protocol.transport = None\n    extra_info = req.get_extra_info(valid_key, default_value)\n    assert extra_info == default_value\n\n    req._protocol = None\n    extra_info = req.get_extra_info(valid_key, default_value)\n    assert extra_info == default_value\n\n\ndef test_eq() -> None:\n    req1 = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    req2 = make_mocked_request(\"GET\", \"/path/to?a=1&b=2\")\n    assert req1 != req2\n    assert req1 == req1\n\n\nasync def test_loop_prop() -> None:\n    loop = asyncio.get_event_loop()\n    req = make_mocked_request(\"GET\", \"/path\", loop=loop)\n    with pytest.deprecated_call(match=r\"^request\\.loop property is deprecated$\"):\n        assert req.loop is loop\n\n\n@pytest.mark.parametrize(\n    [\"header\", \"header_attr\"],\n    [\n        pytest.param(\"If-Match\", \"if_match\"),\n        pytest.param(\"If-None-Match\", \"if_none_match\"),\n    ],\n)\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\n            '\"67ab43\", W/\"54ed21\", \"7892,dd\"',\n            (\n                ETag(is_weak=False, value=\"67ab43\"),\n                ETag(is_weak=True, value=\"54ed21\"),\n                ETag(is_weak=False, value=\"7892,dd\"),\n            ),\n        ),\n        pytest.param(\n            '\"bfc1ef-5b2c2730249c88ca92d82d\"',\n            (ETag(is_weak=False, value=\"bfc1ef-5b2c2730249c88ca92d82d\"),),\n        ),\n        pytest.param(\n            '\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"',\n            (\n                ETag(is_weak=False, value=\"valid-tag\"),\n                ETag(is_weak=False, value=\"also-valid-tag\"),\n            ),\n        ),\n        pytest.param(\n            '\"ascii\", \"это точно не ascii\", \"ascii again\"',\n            (ETag(is_weak=False, value=\"ascii\"),),\n        ),\n        pytest.param(\n            \"*\",\n            (ETag(is_weak=False, value=\"*\"),),\n        ),\n    ],\n)\ndef test_etag_headers(header, header_attr, header_val, expected) -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={header: header_val})\n    assert getattr(req, header_attr) == expected\n\n\n@pytest.mark.parametrize(\n    [\"header\", \"header_attr\"],\n    [\n        pytest.param(\"If-Modified-Since\", \"if_modified_since\"),\n        pytest.param(\"If-Unmodified-Since\", \"if_unmodified_since\"),\n        pytest.param(\"If-Range\", \"if_range\"),\n    ],\n)\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\"xxyyzz\", None),\n        pytest.param(\"Tue, 08 Oct 4446413 00:56:40 GMT\", None),\n        pytest.param(\"Tue, 08 Oct 2000 00:56:80 GMT\", None),\n        pytest.param(\n            \"Tue, 08 Oct 2000 00:56:40 GMT\",\n            datetime.datetime(2000, 10, 8, 0, 56, 40, tzinfo=datetime.timezone.utc),\n        ),\n    ],\n)\ndef test_datetime_headers(header, header_attr, header_val, expected) -> None:\n    req = make_mocked_request(\"GET\", \"/\", headers={header: header_val})\n    assert getattr(req, header_attr) == expected\n",
        "import asyncio\nimport base64\nimport os\nimport socket\nimport ssl\nimport sys\nfrom hashlib import md5, sha1, sha256\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\nfrom typing import Any\nfrom unittest import mock\nfrom uuid import uuid4\n\nimport pytest\n\nfrom aiohttp.http import WS_KEY\nfrom aiohttp.test_utils import loop_context\n\ntry:\n    import trustme\n\n    # Check if the CA is available in runtime, MacOS on Py3.10 fails somehow\n    trustme.CA()\n\n    TRUSTME: bool = True\nexcept ImportError:\n    TRUSTME = False\n\npytest_plugins = [\"aiohttp.pytest_plugin\", \"pytester\"]\n\nIS_HPUX = sys.platform.startswith(\"hp-ux\")\nIS_LINUX = sys.platform.startswith(\"linux\")\n\n\n@pytest.fixture\ndef tls_certificate_authority():\n    if not TRUSTME:\n        pytest.xfail(\"trustme is not supported\")\n    return trustme.CA()\n\n\n@pytest.fixture\ndef tls_certificate(tls_certificate_authority):\n    return tls_certificate_authority.issue_cert(\n        \"localhost\",\n        \"xn--prklad-4va.localhost\",\n        \"127.0.0.1\",\n        \"::1\",\n    )\n\n\n@pytest.fixture\ndef ssl_ctx(tls_certificate):\n    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    tls_certificate.configure_cert(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef client_ssl_ctx(tls_certificate_authority):\n    ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)\n    tls_certificate_authority.configure_trust(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef tls_ca_certificate_pem_path(tls_certificate_authority):\n    with tls_certificate_authority.cert_pem.tempfile() as ca_cert_pem:\n        yield ca_cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_path(tls_certificate):\n    with tls_certificate.private_key_and_cert_chain_pem.tempfile() as cert_pem:\n        yield cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_bytes(tls_certificate):\n    return tls_certificate.cert_chain_pems[0].bytes()\n\n\n@pytest.fixture\ndef tls_certificate_fingerprint_sha256(tls_certificate_pem_bytes):\n    tls_cert_der = ssl.PEM_cert_to_DER_cert(tls_certificate_pem_bytes.decode())\n    return sha256(tls_cert_der).digest()\n\n\n@pytest.fixture\ndef unix_sockname(tmp_path, tmp_path_factory):\n    \"\"\"Generate an fs path to the UNIX domain socket for testing.\n\n    N.B. Different OS kernels have different fs path length limitations\n    for it. For Linux, it's 108, for HP-UX it's 92 (or higher) depending\n    on its version. For for most of the BSDs (Open, Free, macOS) it's\n    mostly 104 but sometimes it can be down to 100.\n\n    Ref: https://github.com/aio-libs/aiohttp/issues/3572\n    \"\"\"\n    if not hasattr(socket, \"AF_UNIX\"):\n        pytest.skip(\"requires UNIX sockets\")\n\n    max_sock_len = 92 if IS_HPUX else 108 if IS_LINUX else 100\n    \"\"\"Amount of bytes allocated for the UNIX socket path by OS kernel.\n\n    Ref: https://unix.stackexchange.com/a/367012/27133\n    \"\"\"\n\n    sock_file_name = \"unix.sock\"\n    unique_prefix = f\"{uuid4()!s}-\"\n    unique_prefix_len = len(unique_prefix.encode())\n\n    root_tmp_dir = Path(\"/tmp\").resolve()\n    os_tmp_dir = Path(os.getenv(\"TMPDIR\", \"/tmp\")).resolve()\n    original_base_tmp_path = Path(\n        str(tmp_path_factory.getbasetemp()),\n    ).resolve()\n\n    original_base_tmp_path_hash = md5(\n        str(original_base_tmp_path).encode(),\n    ).hexdigest()\n\n    def make_tmp_dir(base_tmp_dir):\n        return TemporaryDirectory(\n            dir=str(base_tmp_dir),\n            prefix=\"pt-\",\n            suffix=f\"-{original_base_tmp_path_hash!s}\",\n        )\n\n    def assert_sock_fits(sock_path):\n        sock_path_len = len(sock_path.encode())\n        # exit-check to verify that it's correct and simplify debugging\n        # in the future\n        assert sock_path_len <= max_sock_len, (\n            \"Suggested UNIX socket ({sock_path}) is {sock_path_len} bytes \"\n            \"long but the current kernel only has {max_sock_len} bytes \"\n            \"allocated to hold it so it must be shorter. \"\n            \"See https://github.com/aio-libs/aiohttp/issues/3572 \"\n            \"for more info.\"\n        ).format_map(locals())\n\n    paths = original_base_tmp_path, os_tmp_dir, root_tmp_dir\n    unique_paths = [p for n, p in enumerate(paths) if p not in paths[:n]]\n    paths_num = len(unique_paths)\n\n    for num, tmp_dir_path in enumerate(paths, 1):\n        with make_tmp_dir(tmp_dir_path) as tmpd:\n            tmpd = Path(tmpd).resolve()\n            sock_path = str(tmpd / sock_file_name)\n            sock_path_len = len(sock_path.encode())\n\n            if num >= paths_num:\n                # exit-check to verify that it's correct and simplify\n                # debugging in the future\n                assert_sock_fits(sock_path)\n\n            if sock_path_len <= max_sock_len:\n                if max_sock_len - sock_path_len >= unique_prefix_len:\n                    # If we're lucky to have extra space in the path,\n                    # let's also make it more unique\n                    sock_path = str(tmpd / \"\".join((unique_prefix, sock_file_name)))\n                    # Double-checking it:\n                    assert_sock_fits(sock_path)\n                yield sock_path\n                return\n\n\n@pytest.fixture\ndef pipe_name():\n    name = rf\"\\\\.\\pipe\\{uuid4().hex}\"\n    return name\n\n\n@pytest.fixture\ndef create_mocked_conn(loop: Any):\n    def _proto_factory(conn_closing_result=None, **kwargs):\n        proto = mock.Mock(**kwargs)\n        proto.closed = loop.create_future()\n        proto.closed.set_result(conn_closing_result)\n        return proto\n\n    yield _proto_factory\n\n\n@pytest.fixture\ndef selector_loop():\n    policy = asyncio.WindowsSelectorEventLoopPolicy()\n    asyncio.set_event_loop_policy(policy)\n\n    with loop_context(policy.new_event_loop) as _loop:\n        asyncio.set_event_loop(_loop)\n        yield _loop\n\n\n@pytest.fixture\ndef netrc_contents(\n    tmp_path: Path,\n    monkeypatch: pytest.MonkeyPatch,\n    request: pytest.FixtureRequest,\n):\n    \"\"\"\n    Prepare :file:`.netrc` with given contents.\n\n    Monkey-patches :envvar:`NETRC` to point to created file.\n    \"\"\"\n    netrc_contents = getattr(request, \"param\", None)\n\n    netrc_file_path = tmp_path / \".netrc\"\n    if netrc_contents is not None:\n        netrc_file_path.write_text(netrc_contents)\n\n    monkeypatch.setenv(\"NETRC\", str(netrc_file_path))\n\n    return netrc_file_path\n\n\n@pytest.fixture\ndef start_connection():\n    with mock.patch(\n        \"aiohttp.connector.aiohappyeyeballs.start_connection\",\n        autospec=True,\n        spec_set=True,\n    ) as start_connection_mock:\n        yield start_connection_mock\n\n\n@pytest.fixture\ndef key_data():\n    return os.urandom(16)\n\n\n@pytest.fixture\ndef key(key_data: Any):\n    return base64.b64encode(key_data)\n\n\n@pytest.fixture\ndef ws_key(key: Any):\n    return base64.b64encode(sha1(key + WS_KEY).digest()).decode()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "re-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/requirements/cython.txt\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/hdrs.py\n./tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/_helpers.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/_http_parser.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/_http_writer.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/_websocket.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/_helpers.pyi\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/_cparser.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/_find_header.pxd\ncython -3 -o aiohttp/_helpers.c aiohttp/_helpers.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_parser.c aiohttp/_http_parser.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_writer.c aiohttp/_http_writer.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_websocket.c aiohttp/_websocket.pyx -I aiohttp -Werror\ncd vendor/llhttp; npm ci\n\n> llhttp@9.2.1 prepare\n> npm run clean && npm run build-ts\n\n\n> llhttp@9.2.1 clean\n> rm -rf lib && rm -rf test/tmp\n\n\n> llhttp@9.2.1 build-ts\n> tsc\n\n\nadded 213 packages, and audited 214 packages in 5s\n\n41 packages are looking for funding\n  run `npm fund` for details\n\n5 vulnerabilities (3 moderate, 2 high)\n\nTo address issues that do not require attention, run:\n  npm audit fix\n\nSome issues need review, and may require choosing\na different dependency.\n\nRun `npm audit` for details.\nmake -C vendor/llhttp generate\nmake[1]: Entering directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/vendor/llhttp'\nnpx ts-node bin/generate.ts\nmake[1]: Leaving directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/vendor/llhttp'\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/abc.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/base_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/client.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/client_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/client_proto.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/client_reqrep.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/client_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/compression_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/connector.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/cookiejar.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/formdata.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/http.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/http_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/http_parser.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/http_websocket.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/http_writer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/locks.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/multipart.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/payload.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/payload_streamer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/pytest_plugin.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/resolver.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/streams.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/tcp_helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/test_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/tracing.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/typedefs.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_app.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_fileresponse.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_middlewares.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_request.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_response.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_routedef.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_runner.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_server.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_urldispatcher.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/web_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/aiohttp/worker.py\nuv pip install -e . -c requirements/runtime-deps.txt\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 1 package in 1ms\nPrepared 1 package in 0.24ms\nInstalled 1 package in 37ms\n + pip==24.3.1\nResolved 2 packages in 10ms\nInstalled 2 packages in 12ms\n + cython==3.0.11\n + multidict==6.0.5\nResolved 100 packages in 49ms\nUninstalled 1 package in 7ms\nInstalled 99 packages in 147ms\n + aiodns==3.2.0\n + aiohappyeyeballs==2.4.0\n + aiohttp-theme==0.1.6\n + aioredis==2.0.1\n + aiosignal==1.3.1\n + alabaster==0.7.13\n + annotated-types==0.7.0\n + async-timeout==4.0.3\n + attrs==24.2.0\n + babel==2.16.0\n + blockdiag==3.0.0\n + brotli==1.1.0\n + build==1.2.1\n + certifi==2024.8.30\n + cffi==1.17.0\n + cfgv==3.4.0\n + charset-normalizer==3.3.2\n + cherry-picker==2.2.0\n + click==8.1.7\n + coverage==7.6.1\n + cryptography==43.0.0\n + distlib==0.3.8\n + docutils==0.20.1\n + exceptiongroup==1.2.2\n + filelock==3.15.4\n + freezegun==1.5.1\n + frozenlist==1.4.1\n + funcparserlib==1.0.1\n + gidgethub==5.3.0\n + gunicorn==23.0.0\n + identify==2.6.0\n + idna==3.4\n + imagesize==1.4.1\n + importlib-metadata==8.4.0\n + importlib-resources==6.4.4\n + incremental==24.7.2\n + iniconfig==2.0.0\n + jinja2==3.1.4\n + markdown-it-py==3.0.0\n + markupsafe==2.1.5\n + mdurl==0.1.2\n + mypy==1.11.2\n + mypy-extensions==1.0.0\n + nodeenv==1.9.1\n + packaging==24.1\n + pillow==9.5.0\n - pip==24.3.1\n + pip==24.2\n + pip-tools==7.4.1\n + platformdirs==4.2.2\n + pluggy==1.5.0\n + pre-commit==3.5.0\n + proxy-py==2.4.7\n + pycares==4.4.0\n + pycparser==2.22\n + pydantic==2.8.2\n + pydantic-core==2.20.1\n + pygments==2.18.0\n + pyjwt==2.8.0\n + pyproject-hooks==1.1.0\n + pytest==8.3.2\n + pytest-cov==5.0.0\n + pytest-mock==3.14.0\n + python-dateutil==2.9.0.post0\n + python-on-whales==0.72.0\n + pyyaml==6.0.2\n + re-assert==1.1.0\n + regex==2024.7.24\n + requests==2.32.3\n + rich==13.8.0\n + setuptools==74.0.0\n + setuptools-git==1.2\n + shellingham==1.5.4\n + six==1.16.0\n + slotscheck==0.19.0\n + snowballstemmer==2.2.0\n + sphinx==7.1.2\n + sphinxcontrib-applehelp==1.0.4\n + sphinxcontrib-blockdiag==3.0.0\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n + sphinxcontrib-towncrier==0.4.0a0\n + tomli==2.0.1\n + towncrier==23.11.0\n + tqdm==4.66.5\n + trustme==1.1.0\n + typer==0.12.5\n + typing-extensions==4.12.2\n + uritemplate==4.1.1\n + urllib3==2.2.2\n + uvloop==0.20.0\n + virtualenv==20.26.3\n + wait-for-it==2.2.2\n + webcolors==24.8.0\n + wheel==0.44.0\n + yarl==1.9.7\n + zipp==3.20.1\nResolved 9 packages in 1.73s\nPrepared 1 package in 17.18s\nInstalled 1 package in 0.82ms\n + aiohttp==3.11.0.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3)\nResolved 24 packages in 16ms\nInstalled 5 packages in 5ms\n + async-generator==1.10\n + brotlipy==0.7.0\n + chardet==5.2.0\n + multdict==0.0.5\n + pytest-asyncio==0.25.1\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.2, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 106 items\n\nr2e_tests/test_1.py::test_base_ctor PASSED                               [  0%]\nr2e_tests/test_1.py::test_ctor PASSED                                    [  1%]\nr2e_tests/test_1.py::test_deprecated_message PASSED                      [  2%]\nr2e_tests/test_1.py::test_doubleslashes PASSED                           [  3%]\nr2e_tests/test_1.py::test_content_type_not_specified PASSED              [  4%]\nr2e_tests/test_1.py::test_content_type_from_spec PASSED                  [  5%]\nr2e_tests/test_1.py::test_content_type_from_spec_with_charset PASSED     [  6%]\nr2e_tests/test_1.py::test_calc_content_type_on_getting_charset PASSED    [  7%]\nr2e_tests/test_1.py::test_urlencoded_querystring PASSED                  [  8%]\nr2e_tests/test_1.py::test_non_ascii_path PASSED                          [  9%]\nr2e_tests/test_1.py::test_non_ascii_raw_path PASSED                      [ 10%]\nr2e_tests/test_1.py::test_absolute_url PASSED                            [ 11%]\nr2e_tests/test_1.py::test_clone_absolute_scheme PASSED                   [ 12%]\nr2e_tests/test_1.py::test_clone_absolute_host PASSED                     [ 13%]\nr2e_tests/test_1.py::test_content_length PASSED                          [ 14%]\nr2e_tests/test_1.py::test_range_to_slice_head PASSED                     [ 15%]\nr2e_tests/test_1.py::test_range_to_slice_mid PASSED                      [ 16%]\nr2e_tests/test_1.py::test_range_to_slice_tail_start PASSED               [ 16%]\nr2e_tests/test_1.py::test_range_to_slice_tail_stop PASSED                [ 17%]\nr2e_tests/test_1.py::test_non_keepalive_on_http10 PASSED                 [ 18%]\nr2e_tests/test_1.py::test_non_keepalive_on_closing PASSED                [ 19%]\nr2e_tests/test_1.py::test_call_POST_on_GET_request PASSED                [ 20%]\nr2e_tests/test_1.py::test_call_POST_on_weird_content_type PASSED         [ 21%]\nr2e_tests/test_1.py::test_call_POST_twice PASSED                         [ 22%]\nr2e_tests/test_1.py::test_no_request_cookies PASSED                      [ 23%]\nr2e_tests/test_1.py::test_request_cookie PASSED                          [ 24%]\nr2e_tests/test_1.py::test_request_cookie__set_item PASSED                [ 25%]\nr2e_tests/test_1.py::test_match_info PASSED                              [ 26%]\nr2e_tests/test_1.py::test_request_is_mutable_mapping PASSED              [ 27%]\nr2e_tests/test_1.py::test_request_delitem PASSED                         [ 28%]\nr2e_tests/test_1.py::test_request_len PASSED                             [ 29%]\nr2e_tests/test_1.py::test_request_iter PASSED                            [ 30%]\nr2e_tests/test_1.py::test___repr__ PASSED                                [ 31%]\nr2e_tests/test_1.py::test___repr___non_ascii_path PASSED                 [ 32%]\nr2e_tests/test_1.py::test_http_scheme PASSED                             [ 33%]\nr2e_tests/test_1.py::test_https_scheme_by_ssl_transport PASSED           [ 33%]\nr2e_tests/test_1.py::test_single_forwarded_header PASSED                 [ 34%]\nr2e_tests/test_1.py::test_forwarded_node_identifier[1.2.3.4:1234-1.2.3.4:1234] PASSED [ 35%]\nr2e_tests/test_1.py::test_forwarded_node_identifier[1.2.3.4-1.2.3.4] PASSED [ 36%]\nr2e_tests/test_1.py::test_forwarded_node_identifier[\"[2001:db8:cafe::17]:1234\"-[2001:db8:cafe::17]:1234] PASSED [ 37%]\nr2e_tests/test_1.py::test_forwarded_node_identifier[\"[2001:db8:cafe::17]\"-[2001:db8:cafe::17]] PASSED [ 38%]\nr2e_tests/test_1.py::test_single_forwarded_header_camelcase PASSED       [ 39%]\nr2e_tests/test_1.py::test_single_forwarded_header_single_param PASSED    [ 40%]\nr2e_tests/test_1.py::test_single_forwarded_header_multiple_param PASSED  [ 41%]\nr2e_tests/test_1.py::test_single_forwarded_header_quoted_escaped PASSED  [ 42%]\nr2e_tests/test_1.py::test_single_forwarded_header_custom_param PASSED    [ 43%]\nr2e_tests/test_1.py::test_single_forwarded_header_empty_params PASSED    [ 44%]\nr2e_tests/test_1.py::test_single_forwarded_header_bad_separator PASSED   [ 45%]\nr2e_tests/test_1.py::test_single_forwarded_header_injection1 PASSED      [ 46%]\nr2e_tests/test_1.py::test_single_forwarded_header_injection2 PASSED      [ 47%]\nr2e_tests/test_1.py::test_single_forwarded_header_long_quoted_string PASSED [ 48%]\nr2e_tests/test_1.py::test_multiple_forwarded_headers PASSED              [ 49%]\nr2e_tests/test_1.py::test_multiple_forwarded_headers_bad_syntax PASSED   [ 50%]\nr2e_tests/test_1.py::test_multiple_forwarded_headers_injection PASSED    [ 50%]\nr2e_tests/test_1.py::test_host_by_host_header PASSED                     [ 51%]\nr2e_tests/test_1.py::test_raw_headers PASSED                             [ 52%]\nr2e_tests/test_1.py::test_rel_url PASSED                                 [ 53%]\nr2e_tests/test_1.py::test_url_url PASSED                                 [ 54%]\nr2e_tests/test_1.py::test_clone PASSED                                   [ 55%]\nr2e_tests/test_1.py::test_clone_client_max_size PASSED                   [ 56%]\nr2e_tests/test_1.py::test_clone_override_client_max_size PASSED          [ 57%]\nr2e_tests/test_1.py::test_clone_method PASSED                            [ 58%]\nr2e_tests/test_1.py::test_clone_rel_url PASSED                           [ 59%]\nr2e_tests/test_1.py::test_clone_rel_url_str PASSED                       [ 60%]\nr2e_tests/test_1.py::test_clone_headers PASSED                           [ 61%]\nr2e_tests/test_1.py::test_clone_headers_dict PASSED                      [ 62%]\nr2e_tests/test_1.py::test_cannot_clone_after_read PASSED                 [ 63%]\nr2e_tests/test_1.py::test_make_too_big_request PASSED                    [ 64%]\nr2e_tests/test_1.py::test_make_too_big_request_adjust_limit PASSED       [ 65%]\nr2e_tests/test_1.py::test_multipart_formdata PASSED                      [ 66%]\nr2e_tests/test_1.py::test_multipart_formdata_file PASSED                 [ 66%]\nr2e_tests/test_1.py::test_make_too_big_request_limit_None PASSED         [ 67%]\nr2e_tests/test_1.py::test_remote_peername_tcp PASSED                     [ 68%]\nr2e_tests/test_1.py::test_remote_peername_unix PASSED                    [ 69%]\nr2e_tests/test_1.py::test_save_state_on_clone PASSED                     [ 70%]\nr2e_tests/test_1.py::test_clone_scheme PASSED                            [ 71%]\nr2e_tests/test_1.py::test_clone_host PASSED                              [ 72%]\nr2e_tests/test_1.py::test_clone_remote PASSED                            [ 73%]\nr2e_tests/test_1.py::test_remote_with_closed_transport PASSED            [ 74%]\nr2e_tests/test_1.py::test_url_http_with_closed_transport PASSED          [ 75%]\nr2e_tests/test_1.py::test_url_https_with_closed_transport PASSED         [ 76%]\nr2e_tests/test_1.py::test_get_extra_info PASSED                          [ 77%]\nr2e_tests/test_1.py::test_eq PASSED                                      [ 78%]\nr2e_tests/test_1.py::test_loop_prop PASSED                               [ 79%]\nr2e_tests/test_1.py::test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-Match-if_match] PASSED [ 80%]\nr2e_tests/test_1.py::test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-None-Match-if_none_match] PASSED [ 81%]\nr2e_tests/test_1.py::test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-Match-if_match] PASSED [ 82%]\nr2e_tests/test_1.py::test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-None-Match-if_none_match] PASSED [ 83%]\nr2e_tests/test_1.py::test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-Match-if_match] PASSED [ 83%]\nr2e_tests/test_1.py::test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-None-Match-if_none_match] PASSED [ 84%]\nr2e_tests/test_1.py::test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-Match-if_match] PASSED [ 85%]\nr2e_tests/test_1.py::test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-None-Match-if_none_match] PASSED [ 86%]\nr2e_tests/test_1.py::test_etag_headers[*-expected4-If-Match-if_match] PASSED [ 87%]\nr2e_tests/test_1.py::test_etag_headers[*-expected4-If-None-Match-if_none_match] PASSED [ 88%]\nr2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Modified-Since-if_modified_since] PASSED [ 89%]\nr2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Unmodified-Since-if_unmodified_since] PASSED [ 90%]\nr2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Range-if_range] PASSED [ 91%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Modified-Since-if_modified_since] PASSED [ 92%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Unmodified-Since-if_unmodified_since] PASSED [ 93%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Range-if_range] PASSED [ 94%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Modified-Since-if_modified_since] PASSED [ 95%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Unmodified-Since-if_unmodified_since] PASSED [ 96%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Range-if_range] PASSED [ 97%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Modified-Since-if_modified_since] PASSED [ 98%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Unmodified-Since-if_unmodified_since] PASSED [ 99%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Range-if_range] PASSED [100%]\n\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27     10      2      0    59%\naiohttp/abc.py                              97      8      0      0    92%\naiohttp/base_protocol.py                    67     51     22      0    18%\naiohttp/client.py                          554    403    202      3    21%\naiohttp/client_exceptions.py               154     69     20      0    49%\naiohttp/client_proto.py                    163    130     56      0    15%\naiohttp/client_reqrep.py                   695    522    300      0    18%\naiohttp/client_ws.py                       264    211     82      1    16%\naiohttp/compression_utils.py                70     36     14      0    40%\naiohttp/connector.py                       774    635    321      0    13%\naiohttp/cookiejar.py                       255    200    118      0    15%\naiohttp/formdata.py                         97     79     46      0    13%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         501    285    172      6    37%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     20      4      0    56%\naiohttp/http_parser.py                     504    374    208      8    20%\naiohttp/http_websocket.py                  393    287    152      0    20%\naiohttp/http_writer.py                     118     81     50      1    23%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    329    266     43    40%\naiohttp/payload.py                         237    113     58      1    44%\naiohttp/payload_streamer.py                 31     11      4      0    69%\naiohttp/pytest_plugin.py                   162     95     42      5    39%\naiohttp/resolver.py                         78     58     26      0    19%\naiohttp/streams.py                         398    219    146     24    40%\naiohttp/tcp_helpers.py                      19     11      6      0    32%\naiohttp/test_utils.py                      315    141     50      4    53%\naiohttp/tracing.py                         191     69     32      0    69%\naiohttp/typedefs.py                         23      0      0      0   100%\naiohttp/web.py                             122     84     52      0    23%\naiohttp/web_app.py                         282    189     74      0    26%\naiohttp/web_exceptions.py                  157     19      8      2    85%\naiohttp/web_fileresponse.py                160    126     52      0    18%\naiohttp/web_log.py                         102     58     20      0    36%\naiohttp/web_middlewares.py                  55     42     20      0    17%\naiohttp/web_protocol.py                    354    294    155      0    12%\naiohttp/web_request.py                     445     50    138     13    86%\naiohttp/web_response.py                    479    317    220     13    25%\naiohttp/web_routedef.py                    100     44     10      0    55%\naiohttp/web_runner.py                      213    130     36      0    33%\naiohttp/web_server.py                       42     24     12      0    33%\naiohttp/web_urldispatcher.py               742    463    161      2    31%\naiohttp/web_ws.py                          382    310    132      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          130    130     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              29     29     13      0     0%\ntests/test_classbasedview.py                39     39      0      0     0%\ntests/test_client_connection.py             94     94      2      0     0%\ntests/test_client_exceptions.py            199    199     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2507   2507     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               808    808     18      0     0%\ntests/test_client_response.py              466    466      4      0     0%\ntests/test_client_session.py               556    556     29      0     0%\ntests/test_client_ws.py                    487    487      2      0     0%\ntests/test_client_ws_functional.py         788    788     32      0     0%\ntests/test_connector.py                   1697   1697     82      0     0%\ntests/test_cookiejar.py                    350    350     24      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      81     81      6      0     0%\ntests/test_helpers.py                      470    470     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                 1088   1088     66      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       34     34      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    826    826     32      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       95     95      0      0     0%\ntests/test_proxy.py                        301    301      0      0     0%\ntests/test_proxy_functional.py             459    459     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     191    191     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1076   1076     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   244    244      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  851    851     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               176    176     22      0     0%\ntests/test_web_functional.py              1552   1552     34      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               266    266     12      0     0%\ntests/test_web_request.py                  507    507      8      0     0%\ntests/test_web_request_handler.py           42     42      0      0     0%\ntests/test_web_response.py                 885    885      6      0     0%\ntests/test_web_runner.py                   151    151      4      0     0%\ntests/test_web_sendfile.py                  84     84      0      0     0%\ntests/test_web_sendfile_functional.py      655    655     18      0     0%\ntests/test_web_server.py                   162    162      0      0     0%\ntests/test_web_urldispatcher.py            517    517     24      0     0%\ntests/test_web_websocket.py                401    401      8      0     0%\ntests/test_web_websocket_functional.py     769    769     28      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    34337  30323   4345    127    11%\n\n============================= slowest 10 durations =============================\n0.02s call     r2e_tests/test_1.py::test_get_extra_info\n0.02s call     r2e_tests/test_1.py::test_make_too_big_request_limit_None\n0.02s call     r2e_tests/test_1.py::test_multipart_formdata_file\n0.02s call     r2e_tests/test_1.py::test_loop_prop\n0.02s call     r2e_tests/test_1.py::test_call_POST_on_GET_request\n0.02s call     r2e_tests/test_1.py::test_cannot_clone_after_read\n0.02s call     r2e_tests/test_1.py::test_multipart_formdata\n0.02s call     r2e_tests/test_1.py::test_make_too_big_request_adjust_limit\n0.02s call     r2e_tests/test_1.py::test_make_too_big_request\n0.01s call     r2e_tests/test_1.py::test_base_ctor\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_base_ctor\nPASSED r2e_tests/test_1.py::test_ctor\nPASSED r2e_tests/test_1.py::test_deprecated_message\nPASSED r2e_tests/test_1.py::test_doubleslashes\nPASSED r2e_tests/test_1.py::test_content_type_not_specified\nPASSED r2e_tests/test_1.py::test_content_type_from_spec\nPASSED r2e_tests/test_1.py::test_content_type_from_spec_with_charset\nPASSED r2e_tests/test_1.py::test_calc_content_type_on_getting_charset\nPASSED r2e_tests/test_1.py::test_urlencoded_querystring\nPASSED r2e_tests/test_1.py::test_non_ascii_path\nPASSED r2e_tests/test_1.py::test_non_ascii_raw_path\nPASSED r2e_tests/test_1.py::test_absolute_url\nPASSED r2e_tests/test_1.py::test_clone_absolute_scheme\nPASSED r2e_tests/test_1.py::test_clone_absolute_host\nPASSED r2e_tests/test_1.py::test_content_length\nPASSED r2e_tests/test_1.py::test_range_to_slice_head\nPASSED r2e_tests/test_1.py::test_range_to_slice_mid\nPASSED r2e_tests/test_1.py::test_range_to_slice_tail_start\nPASSED r2e_tests/test_1.py::test_range_to_slice_tail_stop\nPASSED r2e_tests/test_1.py::test_non_keepalive_on_http10\nPASSED r2e_tests/test_1.py::test_non_keepalive_on_closing\nPASSED r2e_tests/test_1.py::test_call_POST_on_GET_request\nPASSED r2e_tests/test_1.py::test_call_POST_on_weird_content_type\nPASSED r2e_tests/test_1.py::test_call_POST_twice\nPASSED r2e_tests/test_1.py::test_no_request_cookies\nPASSED r2e_tests/test_1.py::test_request_cookie\nPASSED r2e_tests/test_1.py::test_request_cookie__set_item\nPASSED r2e_tests/test_1.py::test_match_info\nPASSED r2e_tests/test_1.py::test_request_is_mutable_mapping\nPASSED r2e_tests/test_1.py::test_request_delitem\nPASSED r2e_tests/test_1.py::test_request_len\nPASSED r2e_tests/test_1.py::test_request_iter\nPASSED r2e_tests/test_1.py::test___repr__\nPASSED r2e_tests/test_1.py::test___repr___non_ascii_path\nPASSED r2e_tests/test_1.py::test_http_scheme\nPASSED r2e_tests/test_1.py::test_https_scheme_by_ssl_transport\nPASSED r2e_tests/test_1.py::test_single_forwarded_header\nPASSED r2e_tests/test_1.py::test_forwarded_node_identifier[1.2.3.4:1234-1.2.3.4:1234]\nPASSED r2e_tests/test_1.py::test_forwarded_node_identifier[1.2.3.4-1.2.3.4]\nPASSED r2e_tests/test_1.py::test_forwarded_node_identifier[\"[2001:db8:cafe::17]:1234\"-[2001:db8:cafe::17]:1234]\nPASSED r2e_tests/test_1.py::test_forwarded_node_identifier[\"[2001:db8:cafe::17]\"-[2001:db8:cafe::17]]\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_camelcase\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_single_param\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_multiple_param\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_quoted_escaped\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_custom_param\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_empty_params\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_bad_separator\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_injection1\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_injection2\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_long_quoted_string\nPASSED r2e_tests/test_1.py::test_multiple_forwarded_headers\nPASSED r2e_tests/test_1.py::test_multiple_forwarded_headers_bad_syntax\nPASSED r2e_tests/test_1.py::test_multiple_forwarded_headers_injection\nPASSED r2e_tests/test_1.py::test_host_by_host_header\nPASSED r2e_tests/test_1.py::test_raw_headers\nPASSED r2e_tests/test_1.py::test_rel_url\nPASSED r2e_tests/test_1.py::test_url_url\nPASSED r2e_tests/test_1.py::test_clone\nPASSED r2e_tests/test_1.py::test_clone_client_max_size\nPASSED r2e_tests/test_1.py::test_clone_override_client_max_size\nPASSED r2e_tests/test_1.py::test_clone_method\nPASSED r2e_tests/test_1.py::test_clone_rel_url\nPASSED r2e_tests/test_1.py::test_clone_rel_url_str\nPASSED r2e_tests/test_1.py::test_clone_headers\nPASSED r2e_tests/test_1.py::test_clone_headers_dict\nPASSED r2e_tests/test_1.py::test_cannot_clone_after_read\nPASSED r2e_tests/test_1.py::test_make_too_big_request\nPASSED r2e_tests/test_1.py::test_make_too_big_request_adjust_limit\nPASSED r2e_tests/test_1.py::test_multipart_formdata\nPASSED r2e_tests/test_1.py::test_multipart_formdata_file\nPASSED r2e_tests/test_1.py::test_make_too_big_request_limit_None\nPASSED r2e_tests/test_1.py::test_remote_peername_tcp\nPASSED r2e_tests/test_1.py::test_remote_peername_unix\nPASSED r2e_tests/test_1.py::test_save_state_on_clone\nPASSED r2e_tests/test_1.py::test_clone_scheme\nPASSED r2e_tests/test_1.py::test_clone_host\nPASSED r2e_tests/test_1.py::test_clone_remote\nPASSED r2e_tests/test_1.py::test_remote_with_closed_transport\nPASSED r2e_tests/test_1.py::test_url_http_with_closed_transport\nPASSED r2e_tests/test_1.py::test_url_https_with_closed_transport\nPASSED r2e_tests/test_1.py::test_get_extra_info\nPASSED r2e_tests/test_1.py::test_eq\nPASSED r2e_tests/test_1.py::test_loop_prop\nPASSED r2e_tests/test_1.py::test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[*-expected4-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[*-expected4-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Modified-Since-if_modified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Unmodified-Since-if_unmodified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Range-if_range]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Modified-Since-if_modified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Unmodified-Since-if_unmodified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Range-if_range]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Modified-Since-if_modified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Unmodified-Since-if_unmodified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Range-if_range]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Modified-Since-if_modified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Unmodified-Since-if_unmodified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Range-if_range]\n============================= 106 passed in 5.06s ==============================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.2, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 106 items\n\nr2e_tests/test_1.py::test_base_ctor PASSED                               [  0%]\nr2e_tests/test_1.py::test_ctor PASSED                                    [  1%]\nr2e_tests/test_1.py::test_deprecated_message PASSED                      [  2%]\nr2e_tests/test_1.py::test_doubleslashes PASSED                           [  3%]\nr2e_tests/test_1.py::test_content_type_not_specified PASSED              [  4%]\nr2e_tests/test_1.py::test_content_type_from_spec PASSED                  [  5%]\nr2e_tests/test_1.py::test_content_type_from_spec_with_charset PASSED     [  6%]\nr2e_tests/test_1.py::test_calc_content_type_on_getting_charset PASSED    [  7%]\nr2e_tests/test_1.py::test_urlencoded_querystring PASSED                  [  8%]\nr2e_tests/test_1.py::test_non_ascii_path PASSED                          [  9%]\nr2e_tests/test_1.py::test_non_ascii_raw_path PASSED                      [ 10%]\nr2e_tests/test_1.py::test_absolute_url PASSED                            [ 11%]\nr2e_tests/test_1.py::test_clone_absolute_scheme FAILED                   [ 12%]\nr2e_tests/test_1.py::test_clone_absolute_host FAILED                     [ 13%]\nr2e_tests/test_1.py::test_content_length PASSED                          [ 14%]\nr2e_tests/test_1.py::test_range_to_slice_head PASSED                     [ 15%]\nr2e_tests/test_1.py::test_range_to_slice_mid PASSED                      [ 16%]\nr2e_tests/test_1.py::test_range_to_slice_tail_start PASSED               [ 16%]\nr2e_tests/test_1.py::test_range_to_slice_tail_stop PASSED                [ 17%]\nr2e_tests/test_1.py::test_non_keepalive_on_http10 PASSED                 [ 18%]\nr2e_tests/test_1.py::test_non_keepalive_on_closing PASSED                [ 19%]\nr2e_tests/test_1.py::test_call_POST_on_GET_request PASSED                [ 20%]\nr2e_tests/test_1.py::test_call_POST_on_weird_content_type PASSED         [ 21%]\nr2e_tests/test_1.py::test_call_POST_twice PASSED                         [ 22%]\nr2e_tests/test_1.py::test_no_request_cookies PASSED                      [ 23%]\nr2e_tests/test_1.py::test_request_cookie PASSED                          [ 24%]\nr2e_tests/test_1.py::test_request_cookie__set_item PASSED                [ 25%]\nr2e_tests/test_1.py::test_match_info PASSED                              [ 26%]\nr2e_tests/test_1.py::test_request_is_mutable_mapping PASSED              [ 27%]\nr2e_tests/test_1.py::test_request_delitem PASSED                         [ 28%]\nr2e_tests/test_1.py::test_request_len PASSED                             [ 29%]\nr2e_tests/test_1.py::test_request_iter PASSED                            [ 30%]\nr2e_tests/test_1.py::test___repr__ PASSED                                [ 31%]\nr2e_tests/test_1.py::test___repr___non_ascii_path PASSED                 [ 32%]\nr2e_tests/test_1.py::test_http_scheme PASSED                             [ 33%]\nr2e_tests/test_1.py::test_https_scheme_by_ssl_transport PASSED           [ 33%]\nr2e_tests/test_1.py::test_single_forwarded_header PASSED                 [ 34%]\nr2e_tests/test_1.py::test_forwarded_node_identifier[1.2.3.4:1234-1.2.3.4:1234] PASSED [ 35%]\nr2e_tests/test_1.py::test_forwarded_node_identifier[1.2.3.4-1.2.3.4] PASSED [ 36%]\nr2e_tests/test_1.py::test_forwarded_node_identifier[\"[2001:db8:cafe::17]:1234\"-[2001:db8:cafe::17]:1234] PASSED [ 37%]\nr2e_tests/test_1.py::test_forwarded_node_identifier[\"[2001:db8:cafe::17]\"-[2001:db8:cafe::17]] PASSED [ 38%]\nr2e_tests/test_1.py::test_single_forwarded_header_camelcase PASSED       [ 39%]\nr2e_tests/test_1.py::test_single_forwarded_header_single_param PASSED    [ 40%]\nr2e_tests/test_1.py::test_single_forwarded_header_multiple_param PASSED  [ 41%]\nr2e_tests/test_1.py::test_single_forwarded_header_quoted_escaped PASSED  [ 42%]\nr2e_tests/test_1.py::test_single_forwarded_header_custom_param PASSED    [ 43%]\nr2e_tests/test_1.py::test_single_forwarded_header_empty_params PASSED    [ 44%]\nr2e_tests/test_1.py::test_single_forwarded_header_bad_separator PASSED   [ 45%]\nr2e_tests/test_1.py::test_single_forwarded_header_injection1 PASSED      [ 46%]\nr2e_tests/test_1.py::test_single_forwarded_header_injection2 PASSED      [ 47%]\nr2e_tests/test_1.py::test_single_forwarded_header_long_quoted_string PASSED [ 48%]\nr2e_tests/test_1.py::test_multiple_forwarded_headers PASSED              [ 49%]\nr2e_tests/test_1.py::test_multiple_forwarded_headers_bad_syntax PASSED   [ 50%]\nr2e_tests/test_1.py::test_multiple_forwarded_headers_injection PASSED    [ 50%]\nr2e_tests/test_1.py::test_host_by_host_header PASSED                     [ 51%]\nr2e_tests/test_1.py::test_raw_headers PASSED                             [ 52%]\nr2e_tests/test_1.py::test_rel_url PASSED                                 [ 53%]\nr2e_tests/test_1.py::test_url_url PASSED                                 [ 54%]\nr2e_tests/test_1.py::test_clone PASSED                                   [ 55%]\nr2e_tests/test_1.py::test_clone_client_max_size PASSED                   [ 56%]\nr2e_tests/test_1.py::test_clone_override_client_max_size PASSED          [ 57%]\nr2e_tests/test_1.py::test_clone_method PASSED                            [ 58%]\nr2e_tests/test_1.py::test_clone_rel_url PASSED                           [ 59%]\nr2e_tests/test_1.py::test_clone_rel_url_str PASSED                       [ 60%]\nr2e_tests/test_1.py::test_clone_headers PASSED                           [ 61%]\nr2e_tests/test_1.py::test_clone_headers_dict PASSED                      [ 62%]\nr2e_tests/test_1.py::test_cannot_clone_after_read PASSED                 [ 63%]\nr2e_tests/test_1.py::test_make_too_big_request PASSED                    [ 64%]\nr2e_tests/test_1.py::test_make_too_big_request_adjust_limit PASSED       [ 65%]\nr2e_tests/test_1.py::test_multipart_formdata PASSED                      [ 66%]\nr2e_tests/test_1.py::test_multipart_formdata_file PASSED                 [ 66%]\nr2e_tests/test_1.py::test_make_too_big_request_limit_None PASSED         [ 67%]\nr2e_tests/test_1.py::test_remote_peername_tcp PASSED                     [ 68%]\nr2e_tests/test_1.py::test_remote_peername_unix PASSED                    [ 69%]\nr2e_tests/test_1.py::test_save_state_on_clone PASSED                     [ 70%]\nr2e_tests/test_1.py::test_clone_scheme PASSED                            [ 71%]\nr2e_tests/test_1.py::test_clone_host PASSED                              [ 72%]\nr2e_tests/test_1.py::test_clone_remote PASSED                            [ 73%]\nr2e_tests/test_1.py::test_remote_with_closed_transport PASSED            [ 74%]\nr2e_tests/test_1.py::test_url_http_with_closed_transport PASSED          [ 75%]\nr2e_tests/test_1.py::test_url_https_with_closed_transport PASSED         [ 76%]\nr2e_tests/test_1.py::test_get_extra_info PASSED                          [ 77%]\nr2e_tests/test_1.py::test_eq PASSED                                      [ 78%]\nr2e_tests/test_1.py::test_loop_prop PASSED                               [ 79%]\nr2e_tests/test_1.py::test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-Match-if_match] PASSED [ 80%]\nr2e_tests/test_1.py::test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-None-Match-if_none_match] PASSED [ 81%]\nr2e_tests/test_1.py::test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-Match-if_match] PASSED [ 82%]\nr2e_tests/test_1.py::test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-None-Match-if_none_match] PASSED [ 83%]\nr2e_tests/test_1.py::test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-Match-if_match] PASSED [ 83%]\nr2e_tests/test_1.py::test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-None-Match-if_none_match] PASSED [ 84%]\nr2e_tests/test_1.py::test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-Match-if_match] PASSED [ 85%]\nr2e_tests/test_1.py::test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-None-Match-if_none_match] PASSED [ 86%]\nr2e_tests/test_1.py::test_etag_headers[*-expected4-If-Match-if_match] PASSED [ 87%]\nr2e_tests/test_1.py::test_etag_headers[*-expected4-If-None-Match-if_none_match] PASSED [ 88%]\nr2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Modified-Since-if_modified_since] PASSED [ 89%]\nr2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Unmodified-Since-if_unmodified_since] PASSED [ 90%]\nr2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Range-if_range] PASSED [ 91%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Modified-Since-if_modified_since] PASSED [ 92%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Unmodified-Since-if_unmodified_since] PASSED [ 93%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Range-if_range] PASSED [ 94%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Modified-Since-if_modified_since] PASSED [ 95%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Unmodified-Since-if_unmodified_since] PASSED [ 96%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Range-if_range] PASSED [ 97%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Modified-Since-if_modified_since] PASSED [ 98%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Unmodified-Since-if_unmodified_since] PASSED [ 99%]\nr2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Range-if_range] PASSED [100%]\n\n=================================== FAILURES ===================================\n__________________________ test_clone_absolute_scheme __________________________\n\n    def test_clone_absolute_scheme() -> None:\n        req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n        assert req.scheme == \"https\"\n        req2 = req.clone(scheme=\"http\")\n        assert req2.scheme == \"http\"\n>       assert req2.url.scheme == \"http\"\nE       AssertionError: assert 'https' == 'http'\nE         \nE         - http\nE         + https\nE         ?     +\n\nreq        = <Request GET /path/to >\nreq2       = <Request GET /path/to >\n\nr2e_tests/test_1.py:177: AssertionError\n___________________________ test_clone_absolute_host ___________________________\n\n    def test_clone_absolute_host() -> None:\n        req = make_mocked_request(\"GET\", \"https://example.com/path/to?a=1\")\n        assert req.host == \"example.com\"\n        req2 = req.clone(host=\"foo.test\")\n        assert req2.host == \"foo.test\"\n>       assert req2.url.host == \"foo.test\"\nE       AssertionError: assert 'example.com' == 'foo.test'\nE         \nE         - foo.test\nE         + example.com\n\nreq        = <Request GET /path/to >\nreq2       = <Request GET /path/to >\n\nr2e_tests/test_1.py:185: AssertionError\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27     10      2      0    59%\naiohttp/abc.py                              97      8      0      0    92%\naiohttp/base_protocol.py                    67     51     22      0    18%\naiohttp/client.py                          554    403    202      3    21%\naiohttp/client_exceptions.py               154     69     20      0    49%\naiohttp/client_proto.py                    163    130     56      0    15%\naiohttp/client_reqrep.py                   695    522    300      0    18%\naiohttp/client_ws.py                       264    211     82      1    16%\naiohttp/compression_utils.py                70     36     14      0    40%\naiohttp/connector.py                       774    635    321      0    13%\naiohttp/cookiejar.py                       255    200    118      0    15%\naiohttp/formdata.py                         97     79     46      0    13%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         501    285    172      6    37%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     20      4      0    56%\naiohttp/http_parser.py                     504    374    208      8    20%\naiohttp/http_websocket.py                  393    287    152      0    20%\naiohttp/http_writer.py                     118     81     50      1    23%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    329    266     43    40%\naiohttp/payload.py                         237    113     58      1    44%\naiohttp/payload_streamer.py                 31     11      4      0    69%\naiohttp/pytest_plugin.py                   162     95     42      5    39%\naiohttp/resolver.py                         78     58     26      0    19%\naiohttp/streams.py                         398    219    146     24    40%\naiohttp/tcp_helpers.py                      19     11      6      0    32%\naiohttp/test_utils.py                      315    141     50      4    53%\naiohttp/tracing.py                         191     69     32      0    69%\naiohttp/typedefs.py                         23      0      0      0   100%\naiohttp/web.py                             122     84     52      0    23%\naiohttp/web_app.py                         282    189     74      0    26%\naiohttp/web_exceptions.py                  157     19      8      2    85%\naiohttp/web_fileresponse.py                160    126     52      0    18%\naiohttp/web_log.py                         102     58     20      0    36%\naiohttp/web_middlewares.py                  55     42     20      0    17%\naiohttp/web_protocol.py                    354    294    155      0    12%\naiohttp/web_request.py                     441     50    134     13    86%\naiohttp/web_response.py                    479    317    220     13    25%\naiohttp/web_routedef.py                    100     44     10      0    55%\naiohttp/web_runner.py                      213    130     36      0    33%\naiohttp/web_server.py                       42     24     12      0    33%\naiohttp/web_urldispatcher.py               742    463    161      2    31%\naiohttp/web_ws.py                          382    310    132      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          130    130     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              29     29     13      0     0%\ntests/test_classbasedview.py                39     39      0      0     0%\ntests/test_client_connection.py             94     94      2      0     0%\ntests/test_client_exceptions.py            199    199     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2507   2507     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               808    808     18      0     0%\ntests/test_client_response.py              466    466      4      0     0%\ntests/test_client_session.py               556    556     29      0     0%\ntests/test_client_ws.py                    487    487      2      0     0%\ntests/test_client_ws_functional.py         788    788     32      0     0%\ntests/test_connector.py                   1697   1697     82      0     0%\ntests/test_cookiejar.py                    350    350     24      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      81     81      6      0     0%\ntests/test_helpers.py                      470    470     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                 1088   1088     66      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       34     34      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    826    826     32      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       95     95      0      0     0%\ntests/test_proxy.py                        301    301      0      0     0%\ntests/test_proxy_functional.py             459    459     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     191    191     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1076   1076     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   244    244      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  851    851     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               176    176     22      0     0%\ntests/test_web_functional.py              1552   1552     34      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               266    266     12      0     0%\ntests/test_web_request.py                  490    490      8      0     0%\ntests/test_web_request_handler.py           42     42      0      0     0%\ntests/test_web_response.py                 885    885      6      0     0%\ntests/test_web_runner.py                   151    151      4      0     0%\ntests/test_web_sendfile.py                  84     84      0      0     0%\ntests/test_web_sendfile_functional.py      655    655     18      0     0%\ntests/test_web_server.py                   162    162      0      0     0%\ntests/test_web_urldispatcher.py            517    517     24      0     0%\ntests/test_web_websocket.py                401    401      8      0     0%\ntests/test_web_websocket_functional.py     769    769     28      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    34316  30306   4341    127    11%\n\n============================= slowest 10 durations =============================\n0.02s call     r2e_tests/test_1.py::test_call_POST_on_GET_request\n0.02s call     r2e_tests/test_1.py::test_get_extra_info\n0.02s call     r2e_tests/test_1.py::test_cannot_clone_after_read\n0.02s call     r2e_tests/test_1.py::test_loop_prop\n0.02s call     r2e_tests/test_1.py::test_multipart_formdata\n0.02s call     r2e_tests/test_1.py::test_multipart_formdata_file\n0.02s call     r2e_tests/test_1.py::test_make_too_big_request\n0.01s call     r2e_tests/test_1.py::test_make_too_big_request_adjust_limit\n0.01s call     r2e_tests/test_1.py::test_call_POST_on_weird_content_type\n0.01s call     r2e_tests/test_1.py::test_make_too_big_request_limit_None\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_base_ctor\nPASSED r2e_tests/test_1.py::test_ctor\nPASSED r2e_tests/test_1.py::test_deprecated_message\nPASSED r2e_tests/test_1.py::test_doubleslashes\nPASSED r2e_tests/test_1.py::test_content_type_not_specified\nPASSED r2e_tests/test_1.py::test_content_type_from_spec\nPASSED r2e_tests/test_1.py::test_content_type_from_spec_with_charset\nPASSED r2e_tests/test_1.py::test_calc_content_type_on_getting_charset\nPASSED r2e_tests/test_1.py::test_urlencoded_querystring\nPASSED r2e_tests/test_1.py::test_non_ascii_path\nPASSED r2e_tests/test_1.py::test_non_ascii_raw_path\nPASSED r2e_tests/test_1.py::test_absolute_url\nPASSED r2e_tests/test_1.py::test_content_length\nPASSED r2e_tests/test_1.py::test_range_to_slice_head\nPASSED r2e_tests/test_1.py::test_range_to_slice_mid\nPASSED r2e_tests/test_1.py::test_range_to_slice_tail_start\nPASSED r2e_tests/test_1.py::test_range_to_slice_tail_stop\nPASSED r2e_tests/test_1.py::test_non_keepalive_on_http10\nPASSED r2e_tests/test_1.py::test_non_keepalive_on_closing\nPASSED r2e_tests/test_1.py::test_call_POST_on_GET_request\nPASSED r2e_tests/test_1.py::test_call_POST_on_weird_content_type\nPASSED r2e_tests/test_1.py::test_call_POST_twice\nPASSED r2e_tests/test_1.py::test_no_request_cookies\nPASSED r2e_tests/test_1.py::test_request_cookie\nPASSED r2e_tests/test_1.py::test_request_cookie__set_item\nPASSED r2e_tests/test_1.py::test_match_info\nPASSED r2e_tests/test_1.py::test_request_is_mutable_mapping\nPASSED r2e_tests/test_1.py::test_request_delitem\nPASSED r2e_tests/test_1.py::test_request_len\nPASSED r2e_tests/test_1.py::test_request_iter\nPASSED r2e_tests/test_1.py::test___repr__\nPASSED r2e_tests/test_1.py::test___repr___non_ascii_path\nPASSED r2e_tests/test_1.py::test_http_scheme\nPASSED r2e_tests/test_1.py::test_https_scheme_by_ssl_transport\nPASSED r2e_tests/test_1.py::test_single_forwarded_header\nPASSED r2e_tests/test_1.py::test_forwarded_node_identifier[1.2.3.4:1234-1.2.3.4:1234]\nPASSED r2e_tests/test_1.py::test_forwarded_node_identifier[1.2.3.4-1.2.3.4]\nPASSED r2e_tests/test_1.py::test_forwarded_node_identifier[\"[2001:db8:cafe::17]:1234\"-[2001:db8:cafe::17]:1234]\nPASSED r2e_tests/test_1.py::test_forwarded_node_identifier[\"[2001:db8:cafe::17]\"-[2001:db8:cafe::17]]\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_camelcase\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_single_param\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_multiple_param\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_quoted_escaped\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_custom_param\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_empty_params\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_bad_separator\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_injection1\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_injection2\nPASSED r2e_tests/test_1.py::test_single_forwarded_header_long_quoted_string\nPASSED r2e_tests/test_1.py::test_multiple_forwarded_headers\nPASSED r2e_tests/test_1.py::test_multiple_forwarded_headers_bad_syntax\nPASSED r2e_tests/test_1.py::test_multiple_forwarded_headers_injection\nPASSED r2e_tests/test_1.py::test_host_by_host_header\nPASSED r2e_tests/test_1.py::test_raw_headers\nPASSED r2e_tests/test_1.py::test_rel_url\nPASSED r2e_tests/test_1.py::test_url_url\nPASSED r2e_tests/test_1.py::test_clone\nPASSED r2e_tests/test_1.py::test_clone_client_max_size\nPASSED r2e_tests/test_1.py::test_clone_override_client_max_size\nPASSED r2e_tests/test_1.py::test_clone_method\nPASSED r2e_tests/test_1.py::test_clone_rel_url\nPASSED r2e_tests/test_1.py::test_clone_rel_url_str\nPASSED r2e_tests/test_1.py::test_clone_headers\nPASSED r2e_tests/test_1.py::test_clone_headers_dict\nPASSED r2e_tests/test_1.py::test_cannot_clone_after_read\nPASSED r2e_tests/test_1.py::test_make_too_big_request\nPASSED r2e_tests/test_1.py::test_make_too_big_request_adjust_limit\nPASSED r2e_tests/test_1.py::test_multipart_formdata\nPASSED r2e_tests/test_1.py::test_multipart_formdata_file\nPASSED r2e_tests/test_1.py::test_make_too_big_request_limit_None\nPASSED r2e_tests/test_1.py::test_remote_peername_tcp\nPASSED r2e_tests/test_1.py::test_remote_peername_unix\nPASSED r2e_tests/test_1.py::test_save_state_on_clone\nPASSED r2e_tests/test_1.py::test_clone_scheme\nPASSED r2e_tests/test_1.py::test_clone_host\nPASSED r2e_tests/test_1.py::test_clone_remote\nPASSED r2e_tests/test_1.py::test_remote_with_closed_transport\nPASSED r2e_tests/test_1.py::test_url_http_with_closed_transport\nPASSED r2e_tests/test_1.py::test_url_https_with_closed_transport\nPASSED r2e_tests/test_1.py::test_get_extra_info\nPASSED r2e_tests/test_1.py::test_eq\nPASSED r2e_tests/test_1.py::test_loop_prop\nPASSED r2e_tests/test_1.py::test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[*-expected4-If-Match-if_match]\nPASSED r2e_tests/test_1.py::test_etag_headers[*-expected4-If-None-Match-if_none_match]\nPASSED r2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Modified-Since-if_modified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Unmodified-Since-if_unmodified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[xxyyzz-None-If-Range-if_range]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Modified-Since-if_modified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Unmodified-Since-if_unmodified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Range-if_range]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Modified-Since-if_modified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Unmodified-Since-if_unmodified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Range-if_range]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Modified-Since-if_modified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Unmodified-Since-if_unmodified_since]\nPASSED r2e_tests/test_1.py::test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Range-if_range]\nFAILED r2e_tests/test_1.py::test_clone_absolute_scheme - AssertionError: asse...\nFAILED r2e_tests/test_1.py::test_clone_absolute_host - AssertionError: assert...\n======================== 2 failed, 104 passed in 5.02s =========================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fa628a2170cc03b82f32ea4e3812f41d015125e3/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n"
}
CHANGES/8990.bugfix.rst aiohttp/web_request.py tests/test_web_request.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Cloning a Request Does Not Update Scheme and Host in Absolute URLs

**Description:**

When cloning a request and attempting to change the scheme or host for absolute URLs, the cloned request's URL does not reflect the updated values. This results in the cloned request retaining the original scheme and host instead of the intended changes.

**Example Code:**
```python
from aiohttp import web

async def handler(request):
    cloned_request = request.clone(scheme='http', host='foo.test')
    print(cloned_request.url.scheme)  # Expected: 'http'
    print(cloned_request.url.host)    # Expected: 'foo.test'
    return web.Response()
```

**Expected Behavior:**
The `cloned_request.url` should have the scheme set to `'http'` and the host set to `'foo.test'` as specified during the cloning process.

**Actual Behavior:**
The scheme and host of `cloned_request.url` remain unchanged, retaining their original values `'https'` and `'example.com'` respectively.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### aiohttp/web_request.py
import asyncio
import datetime
import io
import re
import socket
import string
import tempfile
import types
import warnings
from http.cookies import SimpleCookie
from types import MappingProxyType
from typing import (
    TYPE_CHECKING,
    Any,
    Dict,
    Final,
    Iterator,
    Mapping,
    MutableMapping,
    Optional,
    Pattern,
    Tuple,
    Union,
    cast,
)
from urllib.parse import parse_qsl

import attr
from multidict import (
    CIMultiDict,
    CIMultiDictProxy,
    MultiDict,
    MultiDictProxy,
    MultiMapping,
)
from yarl import URL

from . import hdrs
from .abc import AbstractStreamWriter
from .helpers import (
    _SENTINEL,
    DEBUG,
    ETAG_ANY,
    LIST_QUOTED_ETAG_RE,
    ChainMapProxy,
    ETag,
    HeadersMixin,
    parse_http_date,
    reify,
    sentinel,
    set_exception,
)
from .http_parser import RawRequestMessage
from .http_writer import HttpVersion
from .multipart import BodyPartReader, MultipartReader
from .streams import EmptyStreamReader, StreamReader
from .typedefs import (
    DEFAULT_JSON_DECODER,
    JSONDecoder,
    LooseHeaders,
    RawHeaders,
    StrOrURL,
)
from .web_exceptions import HTTPRequestEntityTooLarge
from .web_response import StreamResponse

__all__ = ("BaseRequest", "FileField", "Request")


if TYPE_CHECKING:
    from .web_app import Application
    from .web_protocol import RequestHandler
    from .web_urldispatcher import UrlMappingMatchInfo


@attr.s(auto_attribs=True, frozen=True, slots=True)
class FileField:
    name: str
    filename: str
    file: io.BufferedReader
    content_type: str
    headers: CIMultiDictProxy[str]


_TCHAR: Final[str] = string.digits + string.ascii_letters + r"!#$%&'*+.^_`|~-"
# '-' at the end to prevent interpretation as range in a char class

_TOKEN: Final[str] = rf"[{_TCHAR}]+"

_QDTEXT: Final[str] = r"[{}]".format(
    r"".join(chr(c) for c in (0x09, 0x20, 0x21) + tuple(range(0x23, 0x7F)))
)
# qdtext includes 0x5C to escape 0x5D ('\]')
# qdtext excludes obs-text (because obsoleted, and encoding not specified)

_QUOTED_PAIR: Final[str] = r"\\[\t !-~]"

_QUOTED_STRING: Final[str] = r'"(?:{quoted_pair}|{qdtext})*"'.format(
    qdtext=_QDTEXT, quoted_pair=_QUOTED_PAIR
)

_FORWARDED_PAIR: Final[str] = (
    r"({token})=({token}|{quoted_string})(:\d{{1,4}})?".format(
        token=_TOKEN, quoted_string=_QUOTED_STRING
    )
)

_QUOTED_PAIR_REPLACE_RE: Final[Pattern[str]] = re.compile(r"\\([\t !-~])")
# same pattern as _QUOTED_PAIR but contains a capture group

_FORWARDED_PAIR_RE: Final[Pattern[str]] = re.compile(_FORWARDED_PAIR)

############################################################
# HTTP Request
############################################################


class BaseRequest(MutableMapping[str, Any], HeadersMixin):

    POST_METHODS = {
        hdrs.METH_PATCH,
        hdrs.METH_POST,
        hdrs.METH_PUT,
        hdrs.METH_TRACE,
        hdrs.METH_DELETE,
    }

    ATTRS = HeadersMixin.ATTRS | frozenset(
        [
            "_message",
            "_protocol",
            "_payload_writer",
            "_payload",
            "_headers",
            "_method",
            "_version",
            "_rel_url",
            "_post",
            "_read_bytes",
            "_state",
            "_cache",
            "_task",
            "_client_max_size",
            "_loop",
            "_transport_sslcontext",
            "_transport_peername",
        ]
    )

    def __init__(
        self,
        message: RawRequestMessage,
        payload: StreamReader,
        protocol: "RequestHandler",
        payload_writer: AbstractStreamWriter,
        task: "asyncio.Task[None]",
        loop: asyncio.AbstractEventLoop,
        *,
        client_max_size: int = 1024**2,
        state: Optional[Dict[str, Any]] = None,
        scheme: Optional[str] = None,
        host: Optional[str] = None,
        remote: Optional[str] = None,
    ) -> None:
        if state is None:
            state = {}
        self._message = message
        self._protocol = protocol
        self._payload_writer = payload_writer

        self._payload = payload
        self._headers: CIMultiDictProxy[str] = message.headers
        self._method = message.method
        self._version = message.version
        self._cache: Dict[str, Any] = {}
        url = message.url
        if url.is_absolute():
            # absolute URL is given,
            # override auto-calculating url, host, and scheme
            # all other properties should be good
            self._cache["url"] = url
            self._cache["host"] = url.host
            self._cache["scheme"] = url.scheme
            self._rel_url = url.relative()
        else:
            self._rel_url = message.url
        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None
        self._read_bytes: Optional[bytes] = None

        self._state = state
        self._task = task
        self._client_max_size = client_max_size
        self._loop = loop

        transport = self._protocol.transport
        assert transport is not None
        self._transport_sslcontext = transport.get_extra_info("sslcontext")
        self._transport_peername = transport.get_extra_info("peername")

        if scheme is not None:
            self._cache["scheme"] = scheme
        if host is not None:
            self._cache["host"] = host
        if remote is not None:
            self._cache["remote"] = remote

    def clone(
        self,
        *,
        method: Union[str, _SENTINEL] = sentinel,
        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,
        headers: Union[LooseHeaders, _SENTINEL] = sentinel,
        scheme: Union[str, _SENTINEL] = sentinel,
        host: Union[str, _SENTINEL] = sentinel,
        remote: Union[str, _SENTINEL] = sentinel,
        client_max_size: Union[int, _SENTINEL] = sentinel,
    ) -> "BaseRequest":
        """Clone itself with replacement some attributes.

        Creates and returns a new instance of Request object. If no parameters
        are given, an exact copy is returned. If a parameter is not passed, it
        will reuse the one from the current request object.
        """
        if self._read_bytes:
            raise RuntimeError("Cannot clone request " "after reading its content")

        dct: Dict[str, Any] = {}
        if method is not sentinel:
            dct["method"] = method
        if rel_url is not sentinel:
            new_url: URL = URL(rel_url)
            dct["url"] = new_url
            dct["path"] = str(new_url)
        if headers is not sentinel:
            # a copy semantic
            dct["headers"] = CIMultiDictProxy(CIMultiDict(headers))
            dct["raw_headers"] = tuple(
                (k.encode("utf-8"), v.encode("utf-8"))
                for k, v in dct["headers"].items()
            )

        message = self._message._replace(**dct)

        kwargs = {}
        if scheme is not sentinel:
            kwargs["scheme"] = scheme
        if host is not sentinel:
            kwargs["host"] = host
        if remote is not sentinel:
            kwargs["remote"] = remote
        if client_max_size is sentinel:
            client_max_size = self._client_max_size

        return self.__class__(
            message,
            self._payload,
            self._protocol,
            self._payload_writer,
            self._task,
            self._loop,
            client_max_size=client_max_size,
            state=self._state.copy(),
            **kwargs,
        )

    @property
    def task(self) -> "asyncio.Task[None]":
        return self._task

    @property
    def protocol(self) -> "RequestHandler":
        return self._protocol

    @property
    def transport(self) -> Optional[asyncio.Transport]:
        if self._protocol is None:
            return None
        return self._protocol.transport

    @property
    def writer(self) -> AbstractStreamWriter:
        return self._payload_writer

    @property
    def client_max_size(self) -> int:
        return self._client_max_size

    @reify
    def message(self) -> RawRequestMessage:
        warnings.warn("Request.message is deprecated", DeprecationWarning, stacklevel=3)
        return self._message

    @reify
    def rel_url(self) -> URL:
        return self._rel_url

    @reify
    def loop(self) -> asyncio.AbstractEventLoop:
        warnings.warn(
            "request.loop property is deprecated", DeprecationWarning, stacklevel=2
        )
        return self._loop

    # MutableMapping API

    def __getitem__(self, key: str) -> Any:
        return self._state[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self._state[key] = value

    def __delitem__(self, key: str) -> None:
        del self._state[key]

    def __len__(self) -> int:
        return len(self._state)

    def __iter__(self) -> Iterator[str]:
        return iter(self._state)

    ########

    @reify
    def secure(self) -> bool:
        """A bool indicating if the request is handled with SSL."""
        return self.scheme == "https"

    @reify
    def forwarded(self) -> Tuple[Mapping[str, str], ...]:
        """A tuple containing all parsed Forwarded header(s).

        Makes an effort to parse Forwarded headers as specified by RFC 7239:

        - It adds one (immutable) dictionary per Forwarded 'field-value', ie
          per proxy. The element corresponds to the data in the Forwarded
          field-value added by the first proxy encountered by the client. Each
          subsequent item corresponds to those added by later proxies.
        - It checks that every value has valid syntax in general as specified
          in section 4: either a 'token' or a 'quoted-string'.
        - It un-escapes found escape sequences.
        - It does NOT validate 'by' and 'for' contents as specified in section
          6.
        - It does NOT validate 'host' contents (Host ABNF).
        - It does NOT validate 'proto' contents for valid URI scheme names.

        Returns a tuple containing one or more immutable dicts
        """
        elems = []
        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):
            length = len(field_value)
            pos = 0
            need_separator = False
            elem: Dict[str, str] = {}
            elems.append(types.MappingProxyType(elem))
            while 0 <= pos < length:
                match = _FORWARDED_PAIR_RE.match(field_value, pos)
                if match is not None:  # got a valid forwarded-pair
                    if need_separator:
                        # bad syntax here, skip to next comma
                        pos = field_value.find(",", pos)
                    else:
                        name, value, port = match.groups()
                        if value[0] == '"':
                            # quoted string: remove quotes and unescape
                            value = _QUOTED_PAIR_REPLACE_RE.sub(r"\1", value[1:-1])
                        if port:
                            value += port
                        elem[name.lower()] = value
                        pos += len(match.group(0))
                        need_separator = True
                elif field_value[pos] == ",":  # next forwarded-element
                    need_separator = False
                    elem = {}
                    elems.append(types.MappingProxyType(elem))
                    pos += 1
                elif field_value[pos] == ";":  # next forwarded-pair
                    need_separator = False
                    pos += 1
                elif field_value[pos] in " \t":
                    # Allow whitespace even between forwarded-pairs, though
                    # RFC 7239 doesn't. This simplifies code and is in line
                    # with Postel's law.
                    pos += 1
                else:
                    # bad syntax here, skip to next comma
                    pos = field_value.find(",", pos)
        return tuple(elems)

    @reify
    def scheme(self) -> str:
        """A string representing the scheme of the request.

        Hostname is resolved in this order:

        - overridden value by .clone(scheme=new_scheme) call.
        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.

        'http' or 'https'.
        """
        if self._transport_sslcontext:
            return "https"
        else:
            return "http"

    @reify
    def method(self) -> str:
        """Read only property for getting HTTP method.

        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.
        """
        return self._method

    @reify
    def version(self) -> HttpVersion:
        """Read only property for getting HTTP version of request.

        Returns aiohttp.protocol.HttpVersion instance.
        """
        return self._version

    @reify
    def host(self) -> str:
        """Hostname of the request.

        Hostname is resolved in this order:

        - overridden value by .clone(host=new_host) call.
        - HOST HTTP header
        - socket.getfqdn() value
        """
        host = self._message.headers.get(hdrs.HOST)
        if host is not None:
            return host
        return socket.getfqdn()

    @reify
    def remote(self) -> Optional[str]:
        """Remote IP of client initiated HTTP request.

        The IP is resolved in this order:

        - overridden value by .clone(remote=new_remote) call.
        - peername of opened socket
        """
        if self._transport_peername is None:
            return None
        if isinstance(self._transport_peername, (list, tuple)):
            return str(self._transport_peername[0])
        return str(self._transport_peername)

    @reify
    def url(self) -> URL:
        url = URL.build(scheme=self.scheme, host=self.host)
        return url.join(self._rel_url)

    @reify
    def path(self) -> str:
        """The URL including *PATH INFO* without the host or scheme.

        E.g., ``/app/blog``
        """
        return self._rel_url.path

    @reify
    def path_qs(self) -> str:
        """The URL including PATH_INFO and the query string.

        E.g, /app/blog?id=10
        """
        return str(self._rel_url)

    @reify
    def raw_path(self) -> str:
        """The URL including raw *PATH INFO* without the host or scheme.

        Warning, the path is unquoted and may contains non valid URL characters

        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``
        """
        return self._message.path

    @reify
    def query(self) -> "MultiMapping[str]":
        """A multidict with all the variables in the query string."""
        return MultiDictProxy(self._rel_url.query)

    @reify
    def query_string(self) -> str:
        """The query string in the URL.

        E.g., id=10
        """
        return self._rel_url.query_string

    @reify
    def headers(self) -> CIMultiDictProxy[str]:
        """A case-insensitive multidict proxy with all headers."""
        return self._headers

    @reify
    def raw_headers(self) -> RawHeaders:
        """A sequence of pairs for all headers."""
        return self._message.raw_headers

    @reify
    def if_modified_since(self) -> Optional[datetime.datetime]:
        """The value of If-Modified-Since HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))

    @reify
    def if_unmodified_since(self) -> Optional[datetime.datetime]:
        """The value of If-Unmodified-Since HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))

    @staticmethod
    def _etag_values(etag_header: str) -> Iterator[ETag]:
        """Extract `ETag` objects from raw header."""
        if etag_header == ETAG_ANY:
            yield ETag(
                is_weak=False,
                value=ETAG_ANY,
            )
        else:
            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):
                is_weak, value, garbage = match.group(2, 3, 4)
                # Any symbol captured by 4th group means
                # that the following sequence is invalid.
                if garbage:
                    break

                yield ETag(
                    is_weak=bool(is_weak),
                    value=value,
                )

    @classmethod
    def _if_match_or_none_impl(
        cls, header_value: Optional[str]
    ) -> Optional[Tuple[ETag, ...]]:
        if not header_value:
            return None

        return tuple(cls._etag_values(header_value))

    @reify
    def if_match(self) -> Optional[Tuple[ETag, ...]]:
        """The value of If-Match HTTP header, or None.

        This header is represented as a `tuple` of `ETag` objects.
        """
        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))

    @reify
    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:
        """The value of If-None-Match HTTP header, or None.

        This header is represented as a `tuple` of `ETag` objects.
        """
        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))

    @reify
    def if_range(self) -> Optional[datetime.datetime]:
        """The value of If-Range HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        return parse_http_date(self.headers.get(hdrs.IF_RANGE))

    @reify
    def keep_alive(self) -> bool:
        """Is keepalive enabled by client?"""
        return not self._message.should_close

    @reify
    def cookies(self) -> Mapping[str, str]:
        """Return request cookies.

        A read-only dictionary-like object.
        """
        raw = self.headers.get(hdrs.COOKIE, "")
        parsed = SimpleCookie(raw)
        return MappingProxyType({key: val.value for key, val in parsed.items()})

    @reify
    def http_range(self) -> slice:
        """The content of Range HTTP header.

        Return a slice instance.

        """
        rng = self._headers.get(hdrs.RANGE)
        start, end = None, None
        if rng is not None:
            try:
                pattern = r"^bytes=(\d*)-(\d*)$"
                start, end = re.findall(pattern, rng)[0]
            except IndexError:  # pattern was not found in header
                raise ValueError("range not in acceptable format")

            end = int(end) if end else None
            start = int(start) if start else None

            if start is None and end is not None:
                # end with no start is to return tail of content
                start = -end
                end = None

            if start is not None and end is not None:
                # end is inclusive in range header, exclusive for slice
                end += 1

                if start >= end:
                    raise ValueError("start cannot be after end")

            if start is end is None:  # No valid range supplied
                raise ValueError("No start or end of range specified")

        return slice(start, end, 1)

    @reify
    def content(self) -> StreamReader:
        """Return raw payload stream."""
        return self._payload

    @property
    def has_body(self) -> bool:
        """Return True if request's HTTP BODY can be read, False otherwise."""
        warnings.warn(
            "Deprecated, use .can_read_body #2005", DeprecationWarning, stacklevel=2
        )
        return not self._payload.at_eof()

    @property
    def can_read_body(self) -> bool:
        """Return True if request's HTTP BODY can be read, False otherwise."""
        return not self._payload.at_eof()

    @reify
    def body_exists(self) -> bool:
        """Return True if request has HTTP BODY, False otherwise."""
        return type(self._payload) is not EmptyStreamReader

    async def release(self) -> None:
        """Release request.

        Eat unread part of HTTP BODY if present.
        """
        while not self._payload.at_eof():
            await self._payload.readany()

    async def read(self) -> bytes:
        """Read request body if present.

        Returns bytes object with full request content.
        """
        if self._read_bytes is None:
            body = bytearray()
            while True:
                chunk = await self._payload.readany()
                body.extend(chunk)
                if self._client_max_size:
                    body_size = len(body)
                    if body_size >= self._client_max_size:
                        raise HTTPRequestEntityTooLarge(
                            max_size=self._client_max_size, actual_size=body_size
                        )
                if not chunk:
                    break
            self._read_bytes = bytes(body)
        return self._read_bytes

    async def text(self) -> str:
        """Return BODY as text using encoding from .charset."""
        bytes_body = await self.read()
        encoding = self.charset or "utf-8"
        return bytes_body.decode(encoding)

    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:
        """Return BODY as JSON."""
        body = await self.text()
        return loads(body)

    async def multipart(self) -> MultipartReader:
        """Return async iterator to process BODY as multipart."""
        return MultipartReader(self._headers, self._payload)

    async def post(self) -> "MultiDictProxy[Union[str, bytes, FileField]]":
        """Return POST parameters."""
        if self._post is not None:
            return self._post
        if self._method not in self.POST_METHODS:
            self._post = MultiDictProxy(MultiDict())
            return self._post

        content_type = self.content_type
        if content_type not in (
            "",
            "application/x-www-form-urlencoded",
            "multipart/form-data",
        ):
            self._post = MultiDictProxy(MultiDict())
            return self._post

        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()

        if content_type == "multipart/form-data":
            multipart = await self.multipart()
            max_size = self._client_max_size

            field = await multipart.next()
            while field is not None:
                size = 0
                field_ct = field.headers.get(hdrs.CONTENT_TYPE)

                if isinstance(field, BodyPartReader):
                    assert field.name is not None

                    # Note that according to RFC 7578, the Content-Type header
                    # is optional, even for files, so we can't assume it's
                    # present.
                    # https://tools.ietf.org/html/rfc7578#section-4.4
                    if field.filename:
                        # store file in temp file
                        tmp = await self._loop.run_in_executor(
                            None, tempfile.TemporaryFile
                        )
                        chunk = await field.read_chunk(size=2**16)
                        while chunk:
                            chunk = field.decode(chunk)
                            await self._loop.run_in_executor(None, tmp.write, chunk)
                            size += len(chunk)
                            if 0 < max_size < size:
                                await self._loop.run_in_executor(None, tmp.close)
                                raise HTTPRequestEntityTooLarge(
                                    max_size=max_size, actual_size=size
                                )
                            chunk = await field.read_chunk(size=2**16)
                        await self._loop.run_in_executor(None, tmp.seek, 0)

                        if field_ct is None:
                            field_ct = "application/octet-stream"

                        ff = FileField(
                            field.name,
                            field.filename,
                            cast(io.BufferedReader, tmp),
                            field_ct,
                            field.headers,
                        )
                        out.add(field.name, ff)
                    else:
                        # deal with ordinary data
                        value = await field.read(decode=True)
                        if field_ct is None or field_ct.startswith("text/"):
                            charset = field.get_charset(default="utf-8")
                            out.add(field.name, value.decode(charset))
                        else:
                            out.add(field.name, value)
                        size += len(value)
                        if 0 < max_size < size:
                            raise HTTPRequestEntityTooLarge(
                                max_size=max_size, actual_size=size
                            )
                else:
                    raise ValueError(
                        "To decode nested multipart you need " "to use custom reader",
                    )

                field = await multipart.next()
        else:
            data = await self.read()
            if data:
                charset = self.charset or "utf-8"
                out.extend(
                    parse_qsl(
                        data.rstrip().decode(charset),
                        keep_blank_values=True,
                        encoding=charset,
                    )
                )

        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"
        )
        return "<{} {} {} >".format(
            self.__class__.__name__, self._method, ascii_encodable_path
        )

    def __eq__(self, other: object) -> bool:
        return id(self) == id(other)

    def __bool__(self) -> bool:
        return True

    async def _prepare_hook(self, response: StreamResponse) -> None:
        return

    def _cancel(self, exc: BaseException) -> None:
        set_exception(self._payload, exc)

    def _finish(self) -> None:
        if self._post is None or self.content_type != "multipart/form-data":
            return

        # NOTE: Release file descriptors for the
        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`
        # NOTE: instances of files sent within multipart request body
        # NOTE: via HTTP POST request.
        for file_name, file_field_object in self._post.items():
            if isinstance(file_field_object, FileField):
                file_field_object.file.close()


class Request(BaseRequest):

    ATTRS = BaseRequest.ATTRS | frozenset(["_match_info"])

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)

        # matchdict, route_name, handler
        # or information about traversal lookup

        # initialized after route resolving
        self._match_info: Optional[UrlMappingMatchInfo] = None

    if DEBUG:

        def __setattr__(self, name: str, val: Any) -> None:
            if name not in self.ATTRS:
                warnings.warn(
                    "Setting custom {}.{} attribute "
                    "is discouraged".format(self.__class__.__name__, name),
                    DeprecationWarning,
                    stacklevel=2,
                )
            super().__setattr__(name, val)

    def clone(
        self,
        *,
        method: Union[str, _SENTINEL] = sentinel,
        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,
        headers: Union[LooseHeaders, _SENTINEL] = sentinel,
        scheme: Union[str, _SENTINEL] = sentinel,
        host: Union[str, _SENTINEL] = sentinel,
        remote: Union[str, _SENTINEL] = sentinel,
        client_max_size: Union[int, _SENTINEL] = sentinel,
    ) -> "Request":
        ret = super().clone(
            method=method,
            rel_url=rel_url,
            headers=headers,
            scheme=scheme,
            host=host,
            remote=remote,
            client_max_size=client_max_size,
        )
        new_ret = cast(Request, ret)
        new_ret._match_info = self._match_info
        return new_ret

    @reify
    def match_info(self) -> "UrlMappingMatchInfo":
        """Result of route resolving."""
        match_info = self._match_info
        assert match_info is not None
        return match_info

    @property
    def app(self) -> "Application":
        """Application instance."""
        match_info = self._match_info
        assert match_info is not None
        return match_info.current_app

    @property
    def config_dict(self) -> ChainMapProxy:
        match_info = self._match_info
        assert match_info is not None
        lst = match_info.apps
        app = self.app
        idx = lst.index(app)
        sublist = list(reversed(lst[: idx + 1]))
        return ChainMapProxy(sublist)

    async def _prepare_hook(self, response: StreamResponse) -> None:
        match_info = self._match_info
        if match_info is None:
            return
        for app in match_info._apps:
            await app.on_response_prepare.send(self, response)

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** Cloning a Request Does Not Update Scheme and Host in Absolute URLs

**Description:**

When cloning a request and attempting to change the scheme or host for absolute URLs, the cloned request's URL does not reflect the updated values. This results in the cloned request retaining the original scheme and host instead of the intended changes.

**Example Code:**
```python
from aiohttp import web

async def handler(request):
    cloned_request = request.clone(scheme='http', host='foo.test')
    print(cloned_request.url.scheme)  # Expected: 'http'
    print(cloned_request.url.host)    # Expected: 'foo.test'
    return web.Response()
```

**Expected Behavior:**
The `cloned_request.url` should have the scheme set to `'http'` and the host set to `'foo.test'` as specified during the cloning process.

**Actual Behavior:**
The scheme and host of `cloned_request.url` remain unchanged, retaining their original values `'https'` and `'example.com'` respectively.

[/ISSUE]
{
    "test_base_ctor": "PASSED",
    "test_ctor": "PASSED",
    "test_deprecated_message": "PASSED",
    "test_doubleslashes": "PASSED",
    "test_content_type_not_specified": "PASSED",
    "test_content_type_from_spec": "PASSED",
    "test_content_type_from_spec_with_charset": "PASSED",
    "test_calc_content_type_on_getting_charset": "PASSED",
    "test_urlencoded_querystring": "PASSED",
    "test_non_ascii_path": "PASSED",
    "test_non_ascii_raw_path": "PASSED",
    "test_absolute_url": "PASSED",
    "test_clone_absolute_scheme": "PASSED",
    "test_clone_absolute_host": "PASSED",
    "test_content_length": "PASSED",
    "test_range_to_slice_head": "PASSED",
    "test_range_to_slice_mid": "PASSED",
    "test_range_to_slice_tail_start": "PASSED",
    "test_range_to_slice_tail_stop": "PASSED",
    "test_non_keepalive_on_http10": "PASSED",
    "test_non_keepalive_on_closing": "PASSED",
    "test_call_POST_on_GET_request": "PASSED",
    "test_call_POST_on_weird_content_type": "PASSED",
    "test_call_POST_twice": "PASSED",
    "test_no_request_cookies": "PASSED",
    "test_request_cookie": "PASSED",
    "test_request_cookie__set_item": "PASSED",
    "test_match_info": "PASSED",
    "test_request_is_mutable_mapping": "PASSED",
    "test_request_delitem": "PASSED",
    "test_request_len": "PASSED",
    "test_request_iter": "PASSED",
    "test___repr__": "PASSED",
    "test___repr___non_ascii_path": "PASSED",
    "test_http_scheme": "PASSED",
    "test_https_scheme_by_ssl_transport": "PASSED",
    "test_single_forwarded_header": "PASSED",
    "test_forwarded_node_identifier[1.2.3.4:1234-1.2.3.4:1234]": "PASSED",
    "test_forwarded_node_identifier[1.2.3.4-1.2.3.4]": "PASSED",
    "test_forwarded_node_identifier[\"[2001:db8:cafe.17]:1234\"-[2001:db8:cafe.17]:1234]": "PASSED",
    "test_forwarded_node_identifier[\"[2001:db8:cafe.17]\"-[2001:db8:cafe.17]]": "PASSED",
    "test_single_forwarded_header_camelcase": "PASSED",
    "test_single_forwarded_header_single_param": "PASSED",
    "test_single_forwarded_header_multiple_param": "PASSED",
    "test_single_forwarded_header_quoted_escaped": "PASSED",
    "test_single_forwarded_header_custom_param": "PASSED",
    "test_single_forwarded_header_empty_params": "PASSED",
    "test_single_forwarded_header_bad_separator": "PASSED",
    "test_single_forwarded_header_injection1": "PASSED",
    "test_single_forwarded_header_injection2": "PASSED",
    "test_single_forwarded_header_long_quoted_string": "PASSED",
    "test_multiple_forwarded_headers": "PASSED",
    "test_multiple_forwarded_headers_bad_syntax": "PASSED",
    "test_multiple_forwarded_headers_injection": "PASSED",
    "test_host_by_host_header": "PASSED",
    "test_raw_headers": "PASSED",
    "test_rel_url": "PASSED",
    "test_url_url": "PASSED",
    "test_clone": "PASSED",
    "test_clone_client_max_size": "PASSED",
    "test_clone_override_client_max_size": "PASSED",
    "test_clone_method": "PASSED",
    "test_clone_rel_url": "PASSED",
    "test_clone_rel_url_str": "PASSED",
    "test_clone_headers": "PASSED",
    "test_clone_headers_dict": "PASSED",
    "test_cannot_clone_after_read": "PASSED",
    "test_make_too_big_request": "PASSED",
    "test_make_too_big_request_adjust_limit": "PASSED",
    "test_multipart_formdata": "PASSED",
    "test_multipart_formdata_file": "PASSED",
    "test_make_too_big_request_limit_None": "PASSED",
    "test_remote_peername_tcp": "PASSED",
    "test_remote_peername_unix": "PASSED",
    "test_save_state_on_clone": "PASSED",
    "test_clone_scheme": "PASSED",
    "test_clone_host": "PASSED",
    "test_clone_remote": "PASSED",
    "test_remote_with_closed_transport": "PASSED",
    "test_url_http_with_closed_transport": "PASSED",
    "test_url_https_with_closed_transport": "PASSED",
    "test_get_extra_info": "PASSED",
    "test_eq": "PASSED",
    "test_loop_prop": "PASSED",
    "test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-Match-if_match]": "PASSED",
    "test_etag_headers[\"67ab43\", W/\"54ed21\", \"7892,dd\"-expected0-If-None-Match-if_none_match]": "PASSED",
    "test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-Match-if_match]": "PASSED",
    "test_etag_headers[\"bfc1ef-5b2c2730249c88ca92d82d\"-expected1-If-None-Match-if_none_match]": "PASSED",
    "test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-Match-if_match]": "PASSED",
    "test_etag_headers[\"valid-tag\", \"also-valid-tag\",somegarbage\"last-tag\"-expected2-If-None-Match-if_none_match]": "PASSED",
    "test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-Match-if_match]": "PASSED",
    "test_etag_headers[\"ascii\", \"\\u044d\\u0442\\u043e \\u0442\\u043e\\u0447\\u043d\\u043e \\u043d\\u0435 ascii\", \"ascii again\"-expected3-If-None-Match-if_none_match]": "PASSED",
    "test_etag_headers[*-expected4-If-Match-if_match]": "PASSED",
    "test_etag_headers[*-expected4-If-None-Match-if_none_match]": "PASSED",
    "test_datetime_headers[xxyyzz-None-If-Modified-Since-if_modified_since]": "PASSED",
    "test_datetime_headers[xxyyzz-None-If-Unmodified-Since-if_unmodified_since]": "PASSED",
    "test_datetime_headers[xxyyzz-None-If-Range-if_range]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Modified-Since-if_modified_since]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Unmodified-Since-if_unmodified_since]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 4446413 00:56:40 GMT-None-If-Range-if_range]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Modified-Since-if_modified_since]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Unmodified-Since-if_unmodified_since]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 2000 00:56:80 GMT-None-If-Range-if_range]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Modified-Since-if_modified_since]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Unmodified-Since-if_unmodified_since]": "PASSED",
    "test_datetime_headers[Tue, 08 Oct 2000 00:56:40 GMT-expected3-If-Range-if_range]": "PASSED"
}
diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py
index a63d3074..1d94c576 100644
--- a/aiohttp/web_request.py
+++ b/aiohttp/web_request.py
@@ -175,6 +175,10 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin):
         self._cache: Dict[str, Any] = {}
         url = message.url
         if url.is_absolute():
+            if scheme is not None:
+                url = url.with_scheme(scheme)
+            if host is not None:
+                url = url.with_host(host)
             # absolute URL is given,
             # override auto-calculating url, host, and scheme
             # all other properties should be good
@@ -184,6 +188,10 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin):
             self._rel_url = url.relative()
         else:
             self._rel_url = message.url
+            if scheme is not None:
+                self._cache["scheme"] = scheme
+            if host is not None:
+                self._cache["host"] = host
         self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None
         self._read_bytes: Optional[bytes] = None
 
@@ -197,10 +205,6 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin):
         self._transport_sslcontext = transport.get_extra_info("sslcontext")
         self._transport_peername = transport.get_extra_info("peername")
 
-        if scheme is not None:
-            self._cache["scheme"] = scheme
-        if host is not None:
-            self._cache["host"] = host
         if remote is not None:
             self._cache["remote"] = remote
 

{"aiohttp/web_request.py": "import asyncio\nimport datetime\nimport io\nimport re\nimport socket\nimport string\nimport tempfile\nimport types\nimport warnings\nfrom http.cookies import SimpleCookie\nfrom types import MappingProxyType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    Final,\n    Iterator,\n    Mapping,\n    MutableMapping,\n    Optional,\n    Pattern,\n    Tuple,\n    Union,\n    cast,\n)\nfrom urllib.parse import parse_qsl\n\nimport attr\nfrom multidict import (\n    CIMultiDict,\n    CIMultiDictProxy,\n    MultiDict,\n    MultiDictProxy,\n    MultiMapping,\n)\nfrom yarl import URL\n\nfrom . import hdrs\nfrom .abc import AbstractStreamWriter\nfrom .helpers import (\n    _SENTINEL,\n    DEBUG,\n    ETAG_ANY,\n    LIST_QUOTED_ETAG_RE,\n    ChainMapProxy,\n    ETag,\n    HeadersMixin,\n    parse_http_date,\n    reify,\n    sentinel,\n    set_exception,\n)\nfrom .http_parser import RawRequestMessage\nfrom .http_writer import HttpVersion\nfrom .multipart import BodyPartReader, MultipartReader\nfrom .streams import EmptyStreamReader, StreamReader\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    JSONDecoder,\n    LooseHeaders,\n    RawHeaders,\n    StrOrURL,\n)\nfrom .web_exceptions import HTTPRequestEntityTooLarge\nfrom .web_response import StreamResponse\n\n__all__ = (\"BaseRequest\", \"FileField\", \"Request\")\n\n\nif TYPE_CHECKING:\n    from .web_app import Application\n    from .web_protocol import RequestHandler\n    from .web_urldispatcher import UrlMappingMatchInfo\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass FileField:\n    name: str\n    filename: str\n    file: io.BufferedReader\n    content_type: str\n    headers: CIMultiDictProxy[str]\n\n\n_TCHAR: Final[str] = string.digits + string.ascii_letters + r\"!#$%&'*+.^_`|~-\"\n# '-' at the end to prevent interpretation as range in a char class\n\n_TOKEN: Final[str] = rf\"[{_TCHAR}]+\"\n\n_QDTEXT: Final[str] = r\"[{}]\".format(\n    r\"\".join(chr(c) for c in (0x09, 0x20, 0x21) + tuple(range(0x23, 0x7F)))\n)\n# qdtext includes 0x5C to escape 0x5D ('\\]')\n# qdtext excludes obs-text (because obsoleted, and encoding not specified)\n\n_QUOTED_PAIR: Final[str] = r\"\\\\[\\t !-~]\"\n\n_QUOTED_STRING: Final[str] = r'\"(?:{quoted_pair}|{qdtext})*\"'.format(\n    qdtext=_QDTEXT, quoted_pair=_QUOTED_PAIR\n)\n\n_FORWARDED_PAIR: Final[str] = (\n    r\"({token})=({token}|{quoted_string})(:\\d{{1,4}})?\".format(\n        token=_TOKEN, quoted_string=_QUOTED_STRING\n    )\n)\n\n_QUOTED_PAIR_REPLACE_RE: Final[Pattern[str]] = re.compile(r\"\\\\([\\t !-~])\")\n# same pattern as _QUOTED_PAIR but contains a capture group\n\n_FORWARDED_PAIR_RE: Final[Pattern[str]] = re.compile(_FORWARDED_PAIR)\n\n############################################################\n# HTTP Request\n############################################################\n\n\nclass BaseRequest(MutableMapping[str, Any], HeadersMixin):\n\n    POST_METHODS = {\n        hdrs.METH_PATCH,\n        hdrs.METH_POST,\n        hdrs.METH_PUT,\n        hdrs.METH_TRACE,\n        hdrs.METH_DELETE,\n    }\n\n    ATTRS = HeadersMixin.ATTRS | frozenset(\n        [\n            \"_message\",\n            \"_protocol\",\n            \"_payload_writer\",\n            \"_payload\",\n            \"_headers\",\n            \"_method\",\n            \"_version\",\n            \"_rel_url\",\n            \"_post\",\n            \"_read_bytes\",\n            \"_state\",\n            \"_cache\",\n            \"_task\",\n            \"_client_max_size\",\n            \"_loop\",\n            \"_transport_sslcontext\",\n            \"_transport_peername\",\n        ]\n    )\n\n    def __init__(\n        self,\n        message: RawRequestMessage,\n        payload: StreamReader,\n        protocol: \"RequestHandler\",\n        payload_writer: AbstractStreamWriter,\n        task: \"asyncio.Task[None]\",\n        loop: asyncio.AbstractEventLoop,\n        *,\n        client_max_size: int = 1024**2,\n        state: Optional[Dict[str, Any]] = None,\n        scheme: Optional[str] = None,\n        host: Optional[str] = None,\n        remote: Optional[str] = None,\n    ) -> None:\n        if state is None:\n            state = {}\n        self._message = message\n        self._protocol = protocol\n        self._payload_writer = payload_writer\n\n        self._payload = payload\n        self._headers: CIMultiDictProxy[str] = message.headers\n        self._method = message.method\n        self._version = message.version\n        self._cache: Dict[str, Any] = {}\n        url = message.url\n        if url.is_absolute():\n            # absolute URL is given,\n            # override auto-calculating url, host, and scheme\n            # all other properties should be good\n            self._cache[\"url\"] = url\n            self._cache[\"host\"] = url.host\n            self._cache[\"scheme\"] = url.scheme\n            self._rel_url = url.relative()\n        else:\n            self._rel_url = message.url\n        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None\n        self._read_bytes: Optional[bytes] = None\n\n        self._state = state\n        self._task = task\n        self._client_max_size = client_max_size\n        self._loop = loop\n\n        transport = self._protocol.transport\n        assert transport is not None\n        self._transport_sslcontext = transport.get_extra_info(\"sslcontext\")\n        self._transport_peername = transport.get_extra_info(\"peername\")\n\n        if scheme is not None:\n            self._cache[\"scheme\"] = scheme\n        if host is not None:\n            self._cache[\"host\"] = host\n        if remote is not None:\n            self._cache[\"remote\"] = remote\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"BaseRequest\":\n        \"\"\"Clone itself with replacement some attributes.\n\n        Creates and returns a new instance of Request object. If no parameters\n        are given, an exact copy is returned. If a parameter is not passed, it\n        will reuse the one from the current request object.\n        \"\"\"\n        if self._read_bytes:\n            raise RuntimeError(\"Cannot clone request \" \"after reading its content\")\n\n        dct: Dict[str, Any] = {}\n        if method is not sentinel:\n            dct[\"method\"] = method\n        if rel_url is not sentinel:\n            new_url: URL = URL(rel_url)\n            dct[\"url\"] = new_url\n            dct[\"path\"] = str(new_url)\n        if headers is not sentinel:\n            # a copy semantic\n            dct[\"headers\"] = CIMultiDictProxy(CIMultiDict(headers))\n            dct[\"raw_headers\"] = tuple(\n                (k.encode(\"utf-8\"), v.encode(\"utf-8\"))\n                for k, v in dct[\"headers\"].items()\n            )\n\n        message = self._message._replace(**dct)\n\n        kwargs = {}\n        if scheme is not sentinel:\n            kwargs[\"scheme\"] = scheme\n        if host is not sentinel:\n            kwargs[\"host\"] = host\n        if remote is not sentinel:\n            kwargs[\"remote\"] = remote\n        if client_max_size is sentinel:\n            client_max_size = self._client_max_size\n\n        return self.__class__(\n            message,\n            self._payload,\n            self._protocol,\n            self._payload_writer,\n            self._task,\n            self._loop,\n            client_max_size=client_max_size,\n            state=self._state.copy(),\n            **kwargs,\n        )\n\n    @property\n    def task(self) -> \"asyncio.Task[None]\":\n        return self._task\n\n    @property\n    def protocol(self) -> \"RequestHandler\":\n        return self._protocol\n\n    @property\n    def transport(self) -> Optional[asyncio.Transport]:\n        if self._protocol is None:\n            return None\n        return self._protocol.transport\n\n    @property\n    def writer(self) -> AbstractStreamWriter:\n        return self._payload_writer\n\n    @property\n    def client_max_size(self) -> int:\n        return self._client_max_size\n\n    @reify\n    def message(self) -> RawRequestMessage:\n        warnings.warn(\"Request.message is deprecated\", DeprecationWarning, stacklevel=3)\n        return self._message\n\n    @reify\n    def rel_url(self) -> URL:\n        return self._rel_url\n\n    @reify\n    def loop(self) -> asyncio.AbstractEventLoop:\n        warnings.warn(\n            \"request.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    # MutableMapping API\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    ########\n\n    @reify\n    def secure(self) -> bool:\n        \"\"\"A bool indicating if the request is handled with SSL.\"\"\"\n        return self.scheme == \"https\"\n\n    @reify\n    def forwarded(self) -> Tuple[Mapping[str, str], ...]:\n        \"\"\"A tuple containing all parsed Forwarded header(s).\n\n        Makes an effort to parse Forwarded headers as specified by RFC 7239:\n\n        - It adds one (immutable) dictionary per Forwarded 'field-value', ie\n          per proxy. The element corresponds to the data in the Forwarded\n          field-value added by the first proxy encountered by the client. Each\n          subsequent item corresponds to those added by later proxies.\n        - It checks that every value has valid syntax in general as specified\n          in section 4: either a 'token' or a 'quoted-string'.\n        - It un-escapes found escape sequences.\n        - It does NOT validate 'by' and 'for' contents as specified in section\n          6.\n        - It does NOT validate 'host' contents (Host ABNF).\n        - It does NOT validate 'proto' contents for valid URI scheme names.\n\n        Returns a tuple containing one or more immutable dicts\n        \"\"\"\n        elems = []\n        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):\n            length = len(field_value)\n            pos = 0\n            need_separator = False\n            elem: Dict[str, str] = {}\n            elems.append(types.MappingProxyType(elem))\n            while 0 <= pos < length:\n                match = _FORWARDED_PAIR_RE.match(field_value, pos)\n                if match is not None:  # got a valid forwarded-pair\n                    if need_separator:\n                        # bad syntax here, skip to next comma\n                        pos = field_value.find(\",\", pos)\n                    else:\n                        name, value, port = match.groups()\n                        if value[0] == '\"':\n                            # quoted string: remove quotes and unescape\n                            value = _QUOTED_PAIR_REPLACE_RE.sub(r\"\\1\", value[1:-1])\n                        if port:\n                            value += port\n                        elem[name.lower()] = value\n                        pos += len(match.group(0))\n                        need_separator = True\n                elif field_value[pos] == \",\":  # next forwarded-element\n                    need_separator = False\n                    elem = {}\n                    elems.append(types.MappingProxyType(elem))\n                    pos += 1\n                elif field_value[pos] == \";\":  # next forwarded-pair\n                    need_separator = False\n                    pos += 1\n                elif field_value[pos] in \" \\t\":\n                    # Allow whitespace even between forwarded-pairs, though\n                    # RFC 7239 doesn't. This simplifies code and is in line\n                    # with Postel's law.\n                    pos += 1\n                else:\n                    # bad syntax here, skip to next comma\n                    pos = field_value.find(\",\", pos)\n        return tuple(elems)\n\n    @reify\n    def scheme(self) -> str:\n        \"\"\"A string representing the scheme of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(scheme=new_scheme) call.\n        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport_sslcontext:\n            return \"https\"\n        else:\n            return \"http\"\n\n    @reify\n    def method(self) -> str:\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @reify\n    def version(self) -> HttpVersion:\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @reify\n    def host(self) -> str:\n        \"\"\"Hostname of the request.\n\n        Hostname is resolved in this order:\n\n        - overridden value by .clone(host=new_host) call.\n        - HOST HTTP header\n        - socket.getfqdn() value\n        \"\"\"\n        host = self._message.headers.get(hdrs.HOST)\n        if host is not None:\n            return host\n        return socket.getfqdn()\n\n    @reify\n    def remote(self) -> Optional[str]:\n        \"\"\"Remote IP of client initiated HTTP request.\n\n        The IP is resolved in this order:\n\n        - overridden value by .clone(remote=new_remote) call.\n        - peername of opened socket\n        \"\"\"\n        if self._transport_peername is None:\n            return None\n        if isinstance(self._transport_peername, (list, tuple)):\n            return str(self._transport_peername[0])\n        return str(self._transport_peername)\n\n    @reify\n    def url(self) -> URL:\n        url = URL.build(scheme=self.scheme, host=self.host)\n        return url.join(self._rel_url)\n\n    @reify\n    def path(self) -> str:\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return self._rel_url.path\n\n    @reify\n    def path_qs(self) -> str:\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return str(self._rel_url)\n\n    @reify\n    def raw_path(self) -> str:\n        \"\"\"The URL including raw *PATH INFO* without the host or scheme.\n\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._message.path\n\n    @reify\n    def query(self) -> \"MultiMapping[str]\":\n        \"\"\"A multidict with all the variables in the query string.\"\"\"\n        return MultiDictProxy(self._rel_url.query)\n\n    @reify\n    def query_string(self) -> str:\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._rel_url.query_string\n\n    @reify\n    def headers(self) -> CIMultiDictProxy[str]:\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        \"\"\"A sequence of pairs for all headers.\"\"\"\n        return self._message.raw_headers\n\n    @reify\n    def if_modified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))\n\n    @reify\n    def if_unmodified_since(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Unmodified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))\n\n    @staticmethod\n    def _etag_values(etag_header: str) -> Iterator[ETag]:\n        \"\"\"Extract `ETag` objects from raw header.\"\"\"\n        if etag_header == ETAG_ANY:\n            yield ETag(\n                is_weak=False,\n                value=ETAG_ANY,\n            )\n        else:\n            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):\n                is_weak, value, garbage = match.group(2, 3, 4)\n                # Any symbol captured by 4th group means\n                # that the following sequence is invalid.\n                if garbage:\n                    break\n\n                yield ETag(\n                    is_weak=bool(is_weak),\n                    value=value,\n                )\n\n    @classmethod\n    def _if_match_or_none_impl(\n        cls, header_value: Optional[str]\n    ) -> Optional[Tuple[ETag, ...]]:\n        if not header_value:\n            return None\n\n        return tuple(cls._etag_values(header_value))\n\n    @reify\n    def if_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))\n\n    @reify\n    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:\n        \"\"\"The value of If-None-Match HTTP header, or None.\n\n        This header is represented as a `tuple` of `ETag` objects.\n        \"\"\"\n        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))\n\n    @reify\n    def if_range(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of If-Range HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self.headers.get(hdrs.IF_RANGE))\n\n    @reify\n    def keep_alive(self) -> bool:\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return not self._message.should_close\n\n    @reify\n    def cookies(self) -> Mapping[str, str]:\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        raw = self.headers.get(hdrs.COOKIE, \"\")\n        parsed = SimpleCookie(raw)\n        return MappingProxyType({key: val.value for key, val in parsed.items()})\n\n    @reify\n    def http_range(self) -> slice:\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")\n\n        return slice(start, end, 1)\n\n    @reify\n    def content(self) -> StreamReader:\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        warnings.warn(\n            \"Deprecated, use .can_read_body #2005\", DeprecationWarning, stacklevel=2\n        )\n        return not self._payload.at_eof()\n\n    @property\n    def can_read_body(self) -> bool:\n        \"\"\"Return True if request's HTTP BODY can be read, False otherwise.\"\"\"\n        return not self._payload.at_eof()\n\n    @reify\n    def body_exists(self) -> bool:\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return type(self._payload) is not EmptyStreamReader\n\n    async def release(self) -> None:\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        while not self._payload.at_eof():\n            await self._payload.readany()\n\n    async def read(self) -> bytes:\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = await self._payload.readany()\n                body.extend(chunk)\n                if self._client_max_size:\n                    body_size = len(body)\n                    if body_size >= self._client_max_size:\n                        raise HTTPRequestEntityTooLarge(\n                            max_size=self._client_max_size, actual_size=body_size\n                        )\n                if not chunk:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    async def text(self) -> str:\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = await self.read()\n        encoding = self.charset or \"utf-8\"\n        return bytes_body.decode(encoding)\n\n    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = await self.text()\n        return loads(body)\n\n    async def multipart(self) -> MultipartReader:\n        \"\"\"Return async iterator to process BODY as multipart.\"\"\"\n        return MultipartReader(self._headers, self._payload)\n\n    async def post(self) -> \"MultiDictProxy[Union[str, bytes, FileField]]\":\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self._method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if content_type not in (\n            \"\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\",\n        ):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()\n\n        if content_type == \"multipart/form-data\":\n            multipart = await self.multipart()\n            max_size = self._client_max_size\n\n            field = await multipart.next()\n            while field is not None:\n                size = 0\n                field_ct = field.headers.get(hdrs.CONTENT_TYPE)\n\n                if isinstance(field, BodyPartReader):\n                    assert field.name is not None\n\n                    # Note that according to RFC 7578, the Content-Type header\n                    # is optional, even for files, so we can't assume it's\n                    # present.\n                    # https://tools.ietf.org/html/rfc7578#section-4.4\n                    if field.filename:\n                        # store file in temp file\n                        tmp = await self._loop.run_in_executor(\n                            None, tempfile.TemporaryFile\n                        )\n                        chunk = await field.read_chunk(size=2**16)\n                        while chunk:\n                            chunk = field.decode(chunk)\n                            await self._loop.run_in_executor(None, tmp.write, chunk)\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                await self._loop.run_in_executor(None, tmp.close)\n                                raise HTTPRequestEntityTooLarge(\n                                    max_size=max_size, actual_size=size\n                                )\n                            chunk = await field.read_chunk(size=2**16)\n                        await self._loop.run_in_executor(None, tmp.seek, 0)\n\n                        if field_ct is None:\n                            field_ct = \"application/octet-stream\"\n\n                        ff = FileField(\n                            field.name,\n                            field.filename,\n                            cast(io.BufferedReader, tmp),\n                            field_ct,\n                            field.headers,\n                        )\n                        out.add(field.name, ff)\n                    else:\n                        # deal with ordinary data\n                        value = await field.read(decode=True)\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)\n                        size += len(value)\n                        if 0 < max_size < size:\n                            raise HTTPRequestEntityTooLarge(\n                                max_size=max_size, actual_size=size\n                            )\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need \" \"to use custom reader\",\n                    )\n\n                field = await multipart.next()\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                out.extend(\n                    parse_qsl(\n                        data.rstrip().decode(charset),\n                        keep_blank_values=True,\n                        encoding=charset,\n                    )\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"Extra info from protocol transport\"\"\"\n        protocol = self._protocol\n        if protocol is None:\n            return default\n\n        transport = protocol.transport\n        if transport is None:\n            return default\n\n        return transport.get_extra_info(name, default)\n\n    def __repr__(self) -> str:\n        ascii_encodable_path = self.path.encode(\"ascii\", \"backslashreplace\").decode(\n            \"ascii\"\n        )\n        return \"<{} {} {} >\".format(\n            self.__class__.__name__, self._method, ascii_encodable_path\n        )\n\n    def __eq__(self, other: object) -> bool:\n        return id(self) == id(other)\n\n    def __bool__(self) -> bool:\n        return True\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        return\n\n    def _cancel(self, exc: BaseException) -> None:\n        set_exception(self._payload, exc)\n\n    def _finish(self) -> None:\n        if self._post is None or self.content_type != \"multipart/form-data\":\n            return\n\n        # NOTE: Release file descriptors for the\n        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`\n        # NOTE: instances of files sent within multipart request body\n        # NOTE: via HTTP POST request.\n        for file_name, file_field_object in self._post.items():\n            if isinstance(file_field_object, FileField):\n                file_field_object.file.close()\n\n\nclass Request(BaseRequest):\n\n    ATTRS = BaseRequest.ATTRS | frozenset([\"_match_info\"])\n\n    def __init__(self, *args: Any, **kwargs: Any) -> None:\n        super().__init__(*args, **kwargs)\n\n        # matchdict, route_name, handler\n        # or information about traversal lookup\n\n        # initialized after route resolving\n        self._match_info: Optional[UrlMappingMatchInfo] = None\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom {}.{} attribute \"\n                    \"is discouraged\".format(self.__class__.__name__, name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def clone(\n        self,\n        *,\n        method: Union[str, _SENTINEL] = sentinel,\n        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,\n        headers: Union[LooseHeaders, _SENTINEL] = sentinel,\n        scheme: Union[str, _SENTINEL] = sentinel,\n        host: Union[str, _SENTINEL] = sentinel,\n        remote: Union[str, _SENTINEL] = sentinel,\n        client_max_size: Union[int, _SENTINEL] = sentinel,\n    ) -> \"Request\":\n        ret = super().clone(\n            method=method,\n            rel_url=rel_url,\n            headers=headers,\n            scheme=scheme,\n            host=host,\n            remote=remote,\n            client_max_size=client_max_size,\n        )\n        new_ret = cast(Request, ret)\n        new_ret._match_info = self._match_info\n        return new_ret\n\n    @reify\n    def match_info(self) -> \"UrlMappingMatchInfo\":\n        \"\"\"Result of route resolving.\"\"\"\n        match_info = self._match_info\n        assert match_info is not None\n        return match_info\n\n    @property\n    def app(self) -> \"Application\":\n        \"\"\"Application instance.\"\"\"\n        match_info = self._match_info\n        assert match_info is not None\n        return match_info.current_app\n\n    @property\n    def config_dict(self) -> ChainMapProxy:\n        match_info = self._match_info\n        assert match_info is not None\n        lst = match_info.apps\n        app = self.app\n        idx = lst.index(app)\n        sublist = list(reversed(lst[: idx + 1]))\n        return ChainMapProxy(sublist)\n\n    async def _prepare_hook(self, response: StreamResponse) -> None:\n        match_info = self._match_info\n        if match_info is None:\n            return\n        for app in match_info._apps:\n            await app.on_response_prepare.send(self, response)\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Cloning a Request Does Not Update Scheme and Host in Absolute URLs

**Description:**

When cloning a request and attempting to change the scheme or host for absolute URLs, the cloned request's URL does not reflect the updated values. This results in the cloned request retaining the original scheme and host instead of the intended changes.

**Example Code:**
```python
from aiohttp import web

async def handler(request):
    cloned_request = request.clone(scheme='http', host='foo.test')
    print(cloned_request.url.scheme)  # Expected: 'http'
    print(cloned_request.url.host)    # Expected: 'foo.test'
    return web.Response()
```

**Expected Behavior:**
The `cloned_request.url` should have the scheme set to `'http'` and the host set to `'foo.test'` as specified during the cloning process.

**Actual Behavior:**
The scheme and host of `cloned_request.url` remain unchanged, retaining their original values `'https'` and `'example.com'` respectively.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### aiohttp/web_request.py
import asyncio
import datetime
import io
import re
import socket
import string
import tempfile
import types
import warnings
from http.cookies import SimpleCookie
from types import MappingProxyType
from typing import (
    TYPE_CHECKING,
    Any,
    Dict,
    Final,
    Iterator,
    Mapping,
    MutableMapping,
    Optional,
    Pattern,
    Tuple,
    Union,
    cast,
)
from urllib.parse import parse_qsl

import attr
from multidict import (
    CIMultiDict,
    CIMultiDictProxy,
    MultiDict,
    MultiDictProxy,
    MultiMapping,
)
from yarl import URL

from . import hdrs
from .abc import AbstractStreamWriter
from .helpers import (
    _SENTINEL,
    DEBUG,
    ETAG_ANY,
    LIST_QUOTED_ETAG_RE,
    ChainMapProxy,
    ETag,
    HeadersMixin,
    parse_http_date,
    reify,
    sentinel,
    set_exception,
)
from .http_parser import RawRequestMessage
from .http_writer import HttpVersion
from .multipart import BodyPartReader, MultipartReader
from .streams import EmptyStreamReader, StreamReader
from .typedefs import (
    DEFAULT_JSON_DECODER,
    JSONDecoder,
    LooseHeaders,
    RawHeaders,
    StrOrURL,
)
from .web_exceptions import HTTPRequestEntityTooLarge
from .web_response import StreamResponse

__all__ = ("BaseRequest", "FileField", "Request")


if TYPE_CHECKING:
    from .web_app import Application
    from .web_protocol import RequestHandler
    from .web_urldispatcher import UrlMappingMatchInfo


@attr.s(auto_attribs=True, frozen=True, slots=True)
class FileField:
    name: str
    filename: str
    file: io.BufferedReader
    content_type: str
    headers: CIMultiDictProxy[str]


_TCHAR: Final[str] = string.digits + string.ascii_letters + r"!#$%&'*+.^_`|~-"
# '-' at the end to prevent interpretation as range in a char class

_TOKEN: Final[str] = rf"[{_TCHAR}]+"

_QDTEXT: Final[str] = r"[{}]".format(
    r"".join(chr(c) for c in (0x09, 0x20, 0x21) + tuple(range(0x23, 0x7F)))
)
# qdtext includes 0x5C to escape 0x5D ('\]')
# qdtext excludes obs-text (because obsoleted, and encoding not specified)

_QUOTED_PAIR: Final[str] = r"\\[\t !-~]"

_QUOTED_STRING: Final[str] = r'"(?:{quoted_pair}|{qdtext})*"'.format(
    qdtext=_QDTEXT, quoted_pair=_QUOTED_PAIR
)

_FORWARDED_PAIR: Final[str] = (
    r"({token})=({token}|{quoted_string})(:\d{{1,4}})?".format(
        token=_TOKEN, quoted_string=_QUOTED_STRING
    )
)

_QUOTED_PAIR_REPLACE_RE: Final[Pattern[str]] = re.compile(r"\\([\t !-~])")
# same pattern as _QUOTED_PAIR but contains a capture group

_FORWARDED_PAIR_RE: Final[Pattern[str]] = re.compile(_FORWARDED_PAIR)

############################################################
# HTTP Request
############################################################


class BaseRequest(MutableMapping[str, Any], HeadersMixin):

    POST_METHODS = {
        hdrs.METH_PATCH,
        hdrs.METH_POST,
        hdrs.METH_PUT,
        hdrs.METH_TRACE,
        hdrs.METH_DELETE,
    }

    ATTRS = HeadersMixin.ATTRS | frozenset(
        [
            "_message",
            "_protocol",
            "_payload_writer",
            "_payload",
            "_headers",
            "_method",
            "_version",
            "_rel_url",
            "_post",
            "_read_bytes",
            "_state",
            "_cache",
            "_task",
            "_client_max_size",
            "_loop",
            "_transport_sslcontext",
            "_transport_peername",
        ]
    )

    def __init__(
        self,
        message: RawRequestMessage,
        payload: StreamReader,
        protocol: "RequestHandler",
        payload_writer: AbstractStreamWriter,
        task: "asyncio.Task[None]",
        loop: asyncio.AbstractEventLoop,
        *,
        client_max_size: int = 1024**2,
        state: Optional[Dict[str, Any]] = None,
        scheme: Optional[str] = None,
        host: Optional[str] = None,
        remote: Optional[str] = None,
    ) -> None:
        if state is None:
            state = {}
        self._message = message
        self._protocol = protocol
        self._payload_writer = payload_writer

        self._payload = payload
        self._headers: CIMultiDictProxy[str] = message.headers
        self._method = message.method
        self._version = message.version
        self._cache: Dict[str, Any] = {}
        url = message.url
        if url.is_absolute():
            # absolute URL is given,
            # override auto-calculating url, host, and scheme
            # all other properties should be good
            self._cache["url"] = url
            self._cache["host"] = url.host
            self._cache["scheme"] = url.scheme
            self._rel_url = url.relative()
        else:
            self._rel_url = message.url
        self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None
        self._read_bytes: Optional[bytes] = None

        self._state = state
        self._task = task
        self._client_max_size = client_max_size
        self._loop = loop

        transport = self._protocol.transport
        assert transport is not None
        self._transport_sslcontext = transport.get_extra_info("sslcontext")
        self._transport_peername = transport.get_extra_info("peername")

        if scheme is not None:
            self._cache["scheme"] = scheme
        if host is not None:
            self._cache["host"] = host
        if remote is not None:
            self._cache["remote"] = remote

    def clone(
        self,
        *,
        method: Union[str, _SENTINEL] = sentinel,
        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,
        headers: Union[LooseHeaders, _SENTINEL] = sentinel,
        scheme: Union[str, _SENTINEL] = sentinel,
        host: Union[str, _SENTINEL] = sentinel,
        remote: Union[str, _SENTINEL] = sentinel,
        client_max_size: Union[int, _SENTINEL] = sentinel,
    ) -> "BaseRequest":
        """Clone itself with replacement some attributes.

        Creates and returns a new instance of Request object. If no parameters
        are given, an exact copy is returned. If a parameter is not passed, it
        will reuse the one from the current request object.
        """
        if self._read_bytes:
            raise RuntimeError("Cannot clone request " "after reading its content")

        dct: Dict[str, Any] = {}
        if method is not sentinel:
            dct["method"] = method
        if rel_url is not sentinel:
            new_url: URL = URL(rel_url)
            dct["url"] = new_url
            dct["path"] = str(new_url)
        if headers is not sentinel:
            # a copy semantic
            dct["headers"] = CIMultiDictProxy(CIMultiDict(headers))
            dct["raw_headers"] = tuple(
                (k.encode("utf-8"), v.encode("utf-8"))
                for k, v in dct["headers"].items()
            )

        message = self._message._replace(**dct)

        kwargs = {}
        if scheme is not sentinel:
            kwargs["scheme"] = scheme
        if host is not sentinel:
            kwargs["host"] = host
        if remote is not sentinel:
            kwargs["remote"] = remote
        if client_max_size is sentinel:
            client_max_size = self._client_max_size

        return self.__class__(
            message,
            self._payload,
            self._protocol,
            self._payload_writer,
            self._task,
            self._loop,
            client_max_size=client_max_size,
            state=self._state.copy(),
            **kwargs,
        )

    @property
    def task(self) -> "asyncio.Task[None]":
        return self._task

    @property
    def protocol(self) -> "RequestHandler":
        return self._protocol

    @property
    def transport(self) -> Optional[asyncio.Transport]:
        if self._protocol is None:
            return None
        return self._protocol.transport

    @property
    def writer(self) -> AbstractStreamWriter:
        return self._payload_writer

    @property
    def client_max_size(self) -> int:
        return self._client_max_size

    @reify
    def message(self) -> RawRequestMessage:
        warnings.warn("Request.message is deprecated", DeprecationWarning, stacklevel=3)
        return self._message

    @reify
    def rel_url(self) -> URL:
        return self._rel_url

    @reify
    def loop(self) -> asyncio.AbstractEventLoop:
        warnings.warn(
            "request.loop property is deprecated", DeprecationWarning, stacklevel=2
        )
        return self._loop

    # MutableMapping API

    def __getitem__(self, key: str) -> Any:
        return self._state[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self._state[key] = value

    def __delitem__(self, key: str) -> None:
        del self._state[key]

    def __len__(self) -> int:
        return len(self._state)

    def __iter__(self) -> Iterator[str]:
        return iter(self._state)

    ########

    @reify
    def secure(self) -> bool:
        """A bool indicating if the request is handled with SSL."""
        return self.scheme == "https"

    @reify
    def forwarded(self) -> Tuple[Mapping[str, str], ...]:
        """A tuple containing all parsed Forwarded header(s).

        Makes an effort to parse Forwarded headers as specified by RFC 7239:

        - It adds one (immutable) dictionary per Forwarded 'field-value', ie
          per proxy. The element corresponds to the data in the Forwarded
          field-value added by the first proxy encountered by the client. Each
          subsequent item corresponds to those added by later proxies.
        - It checks that every value has valid syntax in general as specified
          in section 4: either a 'token' or a 'quoted-string'.
        - It un-escapes found escape sequences.
        - It does NOT validate 'by' and 'for' contents as specified in section
          6.
        - It does NOT validate 'host' contents (Host ABNF).
        - It does NOT validate 'proto' contents for valid URI scheme names.

        Returns a tuple containing one or more immutable dicts
        """
        elems = []
        for field_value in self._message.headers.getall(hdrs.FORWARDED, ()):
            length = len(field_value)
            pos = 0
            need_separator = False
            elem: Dict[str, str] = {}
            elems.append(types.MappingProxyType(elem))
            while 0 <= pos < length:
                match = _FORWARDED_PAIR_RE.match(field_value, pos)
                if match is not None:  # got a valid forwarded-pair
                    if need_separator:
                        # bad syntax here, skip to next comma
                        pos = field_value.find(",", pos)
                    else:
                        name, value, port = match.groups()
                        if value[0] == '"':
                            # quoted string: remove quotes and unescape
                            value = _QUOTED_PAIR_REPLACE_RE.sub(r"\1", value[1:-1])
                        if port:
                            value += port
                        elem[name.lower()] = value
                        pos += len(match.group(0))
                        need_separator = True
                elif field_value[pos] == ",":  # next forwarded-element
                    need_separator = False
                    elem = {}
                    elems.append(types.MappingProxyType(elem))
                    pos += 1
                elif field_value[pos] == ";":  # next forwarded-pair
                    need_separator = False
                    pos += 1
                elif field_value[pos] in " \t":
                    # Allow whitespace even between forwarded-pairs, though
                    # RFC 7239 doesn't. This simplifies code and is in line
                    # with Postel's law.
                    pos += 1
                else:
                    # bad syntax here, skip to next comma
                    pos = field_value.find(",", pos)
        return tuple(elems)

    @reify
    def scheme(self) -> str:
        """A string representing the scheme of the request.

        Hostname is resolved in this order:

        - overridden value by .clone(scheme=new_scheme) call.
        - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise.

        'http' or 'https'.
        """
        if self._transport_sslcontext:
            return "https"
        else:
            return "http"

    @reify
    def method(self) -> str:
        """Read only property for getting HTTP method.

        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.
        """
        return self._method

    @reify
    def version(self) -> HttpVersion:
        """Read only property for getting HTTP version of request.

        Returns aiohttp.protocol.HttpVersion instance.
        """
        return self._version

    @reify
    def host(self) -> str:
        """Hostname of the request.

        Hostname is resolved in this order:

        - overridden value by .clone(host=new_host) call.
        - HOST HTTP header
        - socket.getfqdn() value
        """
        host = self._message.headers.get(hdrs.HOST)
        if host is not None:
            return host
        return socket.getfqdn()

    @reify
    def remote(self) -> Optional[str]:
        """Remote IP of client initiated HTTP request.

        The IP is resolved in this order:

        - overridden value by .clone(remote=new_remote) call.
        - peername of opened socket
        """
        if self._transport_peername is None:
            return None
        if isinstance(self._transport_peername, (list, tuple)):
            return str(self._transport_peername[0])
        return str(self._transport_peername)

    @reify
    def url(self) -> URL:
        url = URL.build(scheme=self.scheme, host=self.host)
        return url.join(self._rel_url)

    @reify
    def path(self) -> str:
        """The URL including *PATH INFO* without the host or scheme.

        E.g., ``/app/blog``
        """
        return self._rel_url.path

    @reify
    def path_qs(self) -> str:
        """The URL including PATH_INFO and the query string.

        E.g, /app/blog?id=10
        """
        return str(self._rel_url)

    @reify
    def raw_path(self) -> str:
        """The URL including raw *PATH INFO* without the host or scheme.

        Warning, the path is unquoted and may contains non valid URL characters

        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``
        """
        return self._message.path

    @reify
    def query(self) -> "MultiMapping[str]":
        """A multidict with all the variables in the query string."""
        return MultiDictProxy(self._rel_url.query)

    @reify
    def query_string(self) -> str:
        """The query string in the URL.

        E.g., id=10
        """
        return self._rel_url.query_string

    @reify
    def headers(self) -> CIMultiDictProxy[str]:
        """A case-insensitive multidict proxy with all headers."""
        return self._headers

    @reify
    def raw_headers(self) -> RawHeaders:
        """A sequence of pairs for all headers."""
        return self._message.raw_headers

    @reify
    def if_modified_since(self) -> Optional[datetime.datetime]:
        """The value of If-Modified-Since HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE))

    @reify
    def if_unmodified_since(self) -> Optional[datetime.datetime]:
        """The value of If-Unmodified-Since HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE))

    @staticmethod
    def _etag_values(etag_header: str) -> Iterator[ETag]:
        """Extract `ETag` objects from raw header."""
        if etag_header == ETAG_ANY:
            yield ETag(
                is_weak=False,
                value=ETAG_ANY,
            )
        else:
            for match in LIST_QUOTED_ETAG_RE.finditer(etag_header):
                is_weak, value, garbage = match.group(2, 3, 4)
                # Any symbol captured by 4th group means
                # that the following sequence is invalid.
                if garbage:
                    break

                yield ETag(
                    is_weak=bool(is_weak),
                    value=value,
                )

    @classmethod
    def _if_match_or_none_impl(
        cls, header_value: Optional[str]
    ) -> Optional[Tuple[ETag, ...]]:
        if not header_value:
            return None

        return tuple(cls._etag_values(header_value))

    @reify
    def if_match(self) -> Optional[Tuple[ETag, ...]]:
        """The value of If-Match HTTP header, or None.

        This header is represented as a `tuple` of `ETag` objects.
        """
        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH))

    @reify
    def if_none_match(self) -> Optional[Tuple[ETag, ...]]:
        """The value of If-None-Match HTTP header, or None.

        This header is represented as a `tuple` of `ETag` objects.
        """
        return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH))

    @reify
    def if_range(self) -> Optional[datetime.datetime]:
        """The value of If-Range HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        return parse_http_date(self.headers.get(hdrs.IF_RANGE))

    @reify
    def keep_alive(self) -> bool:
        """Is keepalive enabled by client?"""
        return not self._message.should_close

    @reify
    def cookies(self) -> Mapping[str, str]:
        """Return request cookies.

        A read-only dictionary-like object.
        """
        raw = self.headers.get(hdrs.COOKIE, "")
        parsed = SimpleCookie(raw)
        return MappingProxyType({key: val.value for key, val in parsed.items()})

    @reify
    def http_range(self) -> slice:
        """The content of Range HTTP header.

        Return a slice instance.

        """
        rng = self._headers.get(hdrs.RANGE)
        start, end = None, None
        if rng is not None:
            try:
                pattern = r"^bytes=(\d*)-(\d*)$"
                start, end = re.findall(pattern, rng)[0]
            except IndexError:  # pattern was not found in header
                raise ValueError("range not in acceptable format")

            end = int(end) if end else None
            start = int(start) if start else None

            if start is None and end is not None:
                # end with no start is to return tail of content
                start = -end
                end = None

            if start is not None and end is not None:
                # end is inclusive in range header, exclusive for slice
                end += 1

                if start >= end:
                    raise ValueError("start cannot be after end")

            if start is end is None:  # No valid range supplied
                raise ValueError("No start or end of range specified")

        return slice(start, end, 1)

    @reify
    def content(self) -> StreamReader:
        """Return raw payload stream."""
        return self._payload

    @property
    def has_body(self) -> bool:
        """Return True if request's HTTP BODY can be read, False otherwise."""
        warnings.warn(
            "Deprecated, use .can_read_body #2005", DeprecationWarning, stacklevel=2
        )
        return not self._payload.at_eof()

    @property
    def can_read_body(self) -> bool:
        """Return True if request's HTTP BODY can be read, False otherwise."""
        return not self._payload.at_eof()

    @reify
    def body_exists(self) -> bool:
        """Return True if request has HTTP BODY, False otherwise."""
        return type(self._payload) is not EmptyStreamReader

    async def release(self) -> None:
        """Release request.

        Eat unread part of HTTP BODY if present.
        """
        while not self._payload.at_eof():
            await self._payload.readany()

    async def read(self) -> bytes:
        """Read request body if present.

        Returns bytes object with full request content.
        """
        if self._read_bytes is None:
            body = bytearray()
            while True:
                chunk = await self._payload.readany()
                body.extend(chunk)
                if self._client_max_size:
                    body_size = len(body)
                    if body_size >= self._client_max_size:
                        raise HTTPRequestEntityTooLarge(
                            max_size=self._client_max_size, actual_size=body_size
                        )
                if not chunk:
                    break
            self._read_bytes = bytes(body)
        return self._read_bytes

    async def text(self) -> str:
        """Return BODY as text using encoding from .charset."""
        bytes_body = await self.read()
        encoding = self.charset or "utf-8"
        return bytes_body.decode(encoding)

    async def json(self, *, loads: JSONDecoder = DEFAULT_JSON_DECODER) -> Any:
        """Return BODY as JSON."""
        body = await self.text()
        return loads(body)

    async def multipart(self) -> MultipartReader:
        """Return async iterator to process BODY as multipart."""
        return MultipartReader(self._headers, self._payload)

    async def post(self) -> "MultiDictProxy[Union[str, bytes, FileField]]":
        """Return POST parameters."""
        if self._post is not None:
            return self._post
        if self._method not in self.POST_METHODS:
            self._post = MultiDictProxy(MultiDict())
            return self._post

        content_type = self.content_type
        if content_type not in (
            "",
            "application/x-www-form-urlencoded",
            "multipart/form-data",
        ):
            self._post = MultiDictProxy(MultiDict())
            return self._post

        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()

        if content_type == "multipart/form-data":
            multipart = await self.multipart()
            max_size = self._client_max_size

            field = await multipart.next()
            while field is not None:
                size = 0
                field_ct = field.headers.get(hdrs.CONTENT_TYPE)

                if isinstance(field, BodyPartReader):
                    assert field.name is not None

                    # Note that according to RFC 7578, the Content-Type header
                    # is optional, even for files, so we can't assume it's
                    # present.
                    # https://tools.ietf.org/html/rfc7578#section-4.4
                    if field.filename:
                        # store file in temp file
                        tmp = await self._loop.run_in_executor(
                            None, tempfile.TemporaryFile
                        )
                        chunk = await field.read_chunk(size=2**16)
                        while chunk:
                            chunk = field.decode(chunk)
                            await self._loop.run_in_executor(None, tmp.write, chunk)
                            size += len(chunk)
                            if 0 < max_size < size:
                                await self._loop.run_in_executor(None, tmp.close)
                                raise HTTPRequestEntityTooLarge(
                                    max_size=max_size, actual_size=size
                                )
                            chunk = await field.read_chunk(size=2**16)
                        await self._loop.run_in_executor(None, tmp.seek, 0)

                        if field_ct is None:
                            field_ct = "application/octet-stream"

                        ff = FileField(
                            field.name,
                            field.filename,
                            cast(io.BufferedReader, tmp),
                            field_ct,
                            field.headers,
                        )
                        out.add(field.name, ff)
                    else:
                        # deal with ordinary data
                        value = await field.read(decode=True)
                        if field_ct is None or field_ct.startswith("text/"):
                            charset = field.get_charset(default="utf-8")
                            out.add(field.name, value.decode(charset))
                        else:
                            out.add(field.name, value)
                        size += len(value)
                        if 0 < max_size < size:
                            raise HTTPRequestEntityTooLarge(
                                max_size=max_size, actual_size=size
                            )
                else:
                    raise ValueError(
                        "To decode nested multipart you need " "to use custom reader",
                    )

                field = await multipart.next()
        else:
            data = await self.read()
            if data:
                charset = self.charset or "utf-8"
                out.extend(
                    parse_qsl(
                        data.rstrip().decode(charset),
                        keep_blank_values=True,
                        encoding=charset,
                    )
                )

        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"
        )
        return "<{} {} {} >".format(
            self.__class__.__name__, self._method, ascii_encodable_path
        )

    def __eq__(self, other: object) -> bool:
        return id(self) == id(other)

    def __bool__(self) -> bool:
        return True

    async def _prepare_hook(self, response: StreamResponse) -> None:
        return

    def _cancel(self, exc: BaseException) -> None:
        set_exception(self._payload, exc)

    def _finish(self) -> None:
        if self._post is None or self.content_type != "multipart/form-data":
            return

        # NOTE: Release file descriptors for the
        # NOTE: `tempfile.Temporaryfile`-created `_io.BufferedRandom`
        # NOTE: instances of files sent within multipart request body
        # NOTE: via HTTP POST request.
        for file_name, file_field_object in self._post.items():
            if isinstance(file_field_object, FileField):
                file_field_object.file.close()


class Request(BaseRequest):

    ATTRS = BaseRequest.ATTRS | frozenset(["_match_info"])

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)

        # matchdict, route_name, handler
        # or information about traversal lookup

        # initialized after route resolving
        self._match_info: Optional[UrlMappingMatchInfo] = None

    if DEBUG:

        def __setattr__(self, name: str, val: Any) -> None:
            if name not in self.ATTRS:
                warnings.warn(
                    "Setting custom {}.{} attribute "
                    "is discouraged".format(self.__class__.__name__, name),
                    DeprecationWarning,
                    stacklevel=2,
                )
            super().__setattr__(name, val)

    def clone(
        self,
        *,
        method: Union[str, _SENTINEL] = sentinel,
        rel_url: Union[StrOrURL, _SENTINEL] = sentinel,
        headers: Union[LooseHeaders, _SENTINEL] = sentinel,
        scheme: Union[str, _SENTINEL] = sentinel,
        host: Union[str, _SENTINEL] = sentinel,
        remote: Union[str, _SENTINEL] = sentinel,
        client_max_size: Union[int, _SENTINEL] = sentinel,
    ) -> "Request":
        ret = super().clone(
            method=method,
            rel_url=rel_url,
            headers=headers,
            scheme=scheme,
            host=host,
            remote=remote,
            client_max_size=client_max_size,
        )
        new_ret = cast(Request, ret)
        new_ret._match_info = self._match_info
        return new_ret

    @reify
    def match_info(self) -> "UrlMappingMatchInfo":
        """Result of route resolving."""
        match_info = self._match_info
        assert match_info is not None
        return match_info

    @property
    def app(self) -> "Application":
        """Application instance."""
        match_info = self._match_info
        assert match_info is not None
        return match_info.current_app

    @property
    def config_dict(self) -> ChainMapProxy:
        match_info = self._match_info
        assert match_info is not None
        lst = match_info.apps
        app = self.app
        idx = lst.index(app)
        sublist = list(reversed(lst[: idx + 1]))
        return ChainMapProxy(sublist)

    async def _prepare_hook(self, response: StreamResponse) -> None:
        match_info = self._match_info
        if match_info is None:
            return
        for app in match_info._apps:
            await app.on_response_prepare.send(self, response)

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user