We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ASGI `raw_path` scope key should not include the query string portion.
I ran into a bug where I had written code that assumed `raw_path` as provided by Uvicorn would include the query string, where it turns out not to.

My tests didn't catch this because they were exercising the code using HTTPX ASGI emulation, and it turns out HTTPX thinks that `raw_path` DOES include the query string.

In Uvicorn: https://github.com/encode/uvicorn/blob/93bb8d3879808ae376b57e3721cc227fce2c27c1/uvicorn/protocols/http/h11_impl.py#L207
```python
                raw_path, _, query_string = event.target.partition(b"?")
```
But in HTTPX: https://github.com/encode/httpx/blob/9415af643f23600403740baad0a466edc5cdbec1/httpx/_urls.py#L277-L292

I'm pretty confident HTTPX is incorrect about this. The ASGI spec (coincidentally the one bit of it I contributed directly to) says: https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope

> `raw_path` (*byte string*) -- The original HTTP path component unmodified from the bytes that were received by the web server.

On reading it now I realize this is a little ambiguous.

Daphne (the closest we have to a reference implementation of ASGI) backs up the idea that `raw_path` and `path` should be almost identical except for their encoding:  https://github.com/django/daphne/blob/e49c39a4e5fac8ec170dd653641a9e90844fd3f1/daphne/ws_protocol.py#L77C1-L78

```python
                    "path": unquote(self.path.decode("ascii")),
                    "raw_path": self.path,
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `httpx/_transports/asgi.py`
Content:
```
1 import typing
2 
3 import sniffio
4 
5 from .._models import Request, Response
6 from .._types import AsyncByteStream
7 from .base import AsyncBaseTransport
8 
9 if typing.TYPE_CHECKING:  # pragma: no cover
10     import asyncio
11 
12     import trio
13 
14     Event = typing.Union[asyncio.Event, trio.Event]
15 
16 
17 _Message = typing.Dict[str, typing.Any]
18 _Receive = typing.Callable[[], typing.Awaitable[_Message]]
19 _Send = typing.Callable[
20     [typing.Dict[str, typing.Any]], typing.Coroutine[None, None, None]
21 ]
22 _ASGIApp = typing.Callable[
23     [typing.Dict[str, typing.Any], _Receive, _Send], typing.Coroutine[None, None, None]
24 ]
25 
26 
27 def create_event() -> "Event":
28     if sniffio.current_async_library() == "trio":
29         import trio
30 
31         return trio.Event()
32     else:
33         import asyncio
34 
35         return asyncio.Event()
36 
37 
38 class ASGIResponseStream(AsyncByteStream):
39     def __init__(self, body: typing.List[bytes]) -> None:
40         self._body = body
41 
42     async def __aiter__(self) -> typing.AsyncIterator[bytes]:
43         yield b"".join(self._body)
44 
45 
46 class ASGITransport(AsyncBaseTransport):
47     """
48     A custom AsyncTransport that handles sending requests directly to an ASGI app.
49     The simplest way to use this functionality is to use the `app` argument.
50 
51     ```
52     client = httpx.AsyncClient(app=app)
53     ```
54 
55     Alternatively, you can setup the transport instance explicitly.
56     This allows you to include any additional configuration arguments specific
57     to the ASGITransport class:
58 
59     ```
60     transport = httpx.ASGITransport(
61         app=app,
62         root_path="/submount",
63         client=("1.2.3.4", 123)
64     )
65     client = httpx.AsyncClient(transport=transport)
66     ```
67 
68     Arguments:
69 
70     * `app` - The ASGI application.
71     * `raise_app_exceptions` - Boolean indicating if exceptions in the application
72        should be raised. Default to `True`. Can be set to `False` for use cases
73        such as testing the content of a client 500 response.
74     * `root_path` - The root path on which the ASGI application should be mounted.
75     * `client` - A two-tuple indicating the client IP and port of incoming requests.
76     ```
77     """
78 
79     def __init__(
80         self,
81         app: _ASGIApp,
82         raise_app_exceptions: bool = True,
83         root_path: str = "",
84         client: typing.Tuple[str, int] = ("127.0.0.1", 123),
85     ) -> None:
86         self.app = app
87         self.raise_app_exceptions = raise_app_exceptions
88         self.root_path = root_path
89         self.client = client
90 
91     async def handle_async_request(
92         self,
93         request: Request,
94     ) -> Response:
95         assert isinstance(request.stream, AsyncByteStream)
96 
97         # ASGI scope.
98         scope = {
99             "type": "http",
100             "asgi": {"version": "3.0"},
101             "http_version": "1.1",
102             "method": request.method,
103             "headers": [(k.lower(), v) for (k, v) in request.headers.raw],
104             "scheme": request.url.scheme,
105             "path": request.url.path,
106             "raw_path": request.url.raw_path,
107             "query_string": request.url.query,
108             "server": (request.url.host, request.url.port),
109             "client": self.client,
110             "root_path": self.root_path,
111         }
112 
113         # Request.
114         request_body_chunks = request.stream.__aiter__()
115         request_complete = False
116 
117         # Response.
118         status_code = None
119         response_headers = None
120         body_parts = []
121         response_started = False
122         response_complete = create_event()
123 
124         # ASGI callables.
125 
126         async def receive() -> typing.Dict[str, typing.Any]:
127             nonlocal request_complete
128 
129             if request_complete:
130                 await response_complete.wait()
131                 return {"type": "http.disconnect"}
132 
133             try:
134                 body = await request_body_chunks.__anext__()
135             except StopAsyncIteration:
136                 request_complete = True
137                 return {"type": "http.request", "body": b"", "more_body": False}
138             return {"type": "http.request", "body": body, "more_body": True}
139 
140         async def send(message: typing.Dict[str, typing.Any]) -> None:
141             nonlocal status_code, response_headers, response_started
142 
143             if message["type"] == "http.response.start":
144                 assert not response_started
145 
146                 status_code = message["status"]
147                 response_headers = message.get("headers", [])
148                 response_started = True
149 
150             elif message["type"] == "http.response.body":
151                 assert not response_complete.is_set()
152                 body = message.get("body", b"")
153                 more_body = message.get("more_body", False)
154 
155                 if body and request.method != "HEAD":
156                     body_parts.append(body)
157 
158                 if not more_body:
159                     response_complete.set()
160 
161         try:
162             await self.app(scope, receive, send)
163         except Exception:  # noqa: PIE-786
164             if self.raise_app_exceptions:
165                 raise
166 
167             response_complete.set()
168             if status_code is None:
169                 status_code = 500
170             if response_headers is None:
171                 response_headers = {}
172 
173         assert response_complete.is_set()
174         assert status_code is not None
175         assert response_headers is not None
176 
177         stream = ASGIResponseStream(body_parts)
178 
179         return Response(status_code, headers=response_headers, stream=stream)
180
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/httpx/_transports/asgi.py b/httpx/_transports/asgi.py
--- a/httpx/_transports/asgi.py
+++ b/httpx/_transports/asgi.py
@@ -103,7 +103,7 @@
             "headers": [(k.lower(), v) for (k, v) in request.headers.raw],
             "scheme": request.url.scheme,
             "path": request.url.path,
-            "raw_path": request.url.raw_path,
+            "raw_path": request.url.raw_path.split(b"?")[0],
             "query_string": request.url.query,
             "server": (request.url.host, request.url.port),
             "client": self.client,

{"golden_diff": "diff --git a/httpx/_transports/asgi.py b/httpx/_transports/asgi.py\n--- a/httpx/_transports/asgi.py\n+++ b/httpx/_transports/asgi.py\n@@ -103,7 +103,7 @@\n             \"headers\": [(k.lower(), v) for (k, v) in request.headers.raw],\n             \"scheme\": request.url.scheme,\n             \"path\": request.url.path,\n-            \"raw_path\": request.url.raw_path,\n+            \"raw_path\": request.url.raw_path.split(b\"?\")[0],\n             \"query_string\": request.url.query,\n             \"server\": (request.url.host, request.url.port),\n             \"client\": self.client,\n", "issue": "ASGI `raw_path` scope key should not include the query string portion.\nI ran into a bug where I had written code that assumed `raw_path` as provided by Uvicorn would include the query string, where it turns out not to.\r\n\r\nMy tests didn't catch this because they were exercising the code using HTTPX ASGI emulation, and it turns out HTTPX thinks that `raw_path` DOES include the query string.\r\n\r\nIn Uvicorn: https://github.com/encode/uvicorn/blob/93bb8d3879808ae376b57e3721cc227fce2c27c1/uvicorn/protocols/http/h11_impl.py#L207\r\n```python\r\n                raw_path, _, query_string = event.target.partition(b\"?\")\r\n```\r\nBut in HTTPX: https://github.com/encode/httpx/blob/9415af643f23600403740baad0a466edc5cdbec1/httpx/_urls.py#L277-L292\r\n\r\nI'm pretty confident HTTPX is incorrect about this. The ASGI spec (coincidentally the one bit of it I contributed directly to) says: https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope\r\n\r\n> `raw_path` (*byte string*) -- The original HTTP path component unmodified from the bytes that were received by the web server.\r\n\r\nOn reading it now I realize this is a little ambiguous.\r\n\r\nDaphne (the closest we have to a reference implementation of ASGI) backs up the idea that `raw_path` and `path` should be almost identical except for their encoding:  https://github.com/django/daphne/blob/e49c39a4e5fac8ec170dd653641a9e90844fd3f1/daphne/ws_protocol.py#L77C1-L78\r\n\r\n```python\r\n                    \"path\": unquote(self.path.decode(\"ascii\")),\r\n                    \"raw_path\": self.path,\r\n```\n", "before_files": [{"content": "import typing\n\nimport sniffio\n\nfrom .._models import Request, Response\nfrom .._types import AsyncByteStream\nfrom .base import AsyncBaseTransport\n\nif typing.TYPE_CHECKING:  # pragma: no cover\n    import asyncio\n\n    import trio\n\n    Event = typing.Union[asyncio.Event, trio.Event]\n\n\n_Message = typing.Dict[str, typing.Any]\n_Receive = typing.Callable[[], typing.Awaitable[_Message]]\n_Send = typing.Callable[\n    [typing.Dict[str, typing.Any]], typing.Coroutine[None, None, None]\n]\n_ASGIApp = typing.Callable[\n    [typing.Dict[str, typing.Any], _Receive, _Send], typing.Coroutine[None, None, None]\n]\n\n\ndef create_event() -> \"Event\":\n    if sniffio.current_async_library() == \"trio\":\n        import trio\n\n        return trio.Event()\n    else:\n        import asyncio\n\n        return asyncio.Event()\n\n\nclass ASGIResponseStream(AsyncByteStream):\n    def __init__(self, body: typing.List[bytes]) -> None:\n        self._body = body\n\n    async def __aiter__(self) -> typing.AsyncIterator[bytes]:\n        yield b\"\".join(self._body)\n\n\nclass ASGITransport(AsyncBaseTransport):\n    \"\"\"\n    A custom AsyncTransport that handles sending requests directly to an ASGI app.\n    The simplest way to use this functionality is to use the `app` argument.\n\n    ```\n    client = httpx.AsyncClient(app=app)\n    ```\n\n    Alternatively, you can setup the transport instance explicitly.\n    This allows you to include any additional configuration arguments specific\n    to the ASGITransport class:\n\n    ```\n    transport = httpx.ASGITransport(\n        app=app,\n        root_path=\"/submount\",\n        client=(\"1.2.3.4\", 123)\n    )\n    client = httpx.AsyncClient(transport=transport)\n    ```\n\n    Arguments:\n\n    * `app` - The ASGI application.\n    * `raise_app_exceptions` - Boolean indicating if exceptions in the application\n       should be raised. Default to `True`. Can be set to `False` for use cases\n       such as testing the content of a client 500 response.\n    * `root_path` - The root path on which the ASGI application should be mounted.\n    * `client` - A two-tuple indicating the client IP and port of incoming requests.\n    ```\n    \"\"\"\n\n    def __init__(\n        self,\n        app: _ASGIApp,\n        raise_app_exceptions: bool = True,\n        root_path: str = \"\",\n        client: typing.Tuple[str, int] = (\"127.0.0.1\", 123),\n    ) -> None:\n        self.app = app\n        self.raise_app_exceptions = raise_app_exceptions\n        self.root_path = root_path\n        self.client = client\n\n    async def handle_async_request(\n        self,\n        request: Request,\n    ) -> Response:\n        assert isinstance(request.stream, AsyncByteStream)\n\n        # ASGI scope.\n        scope = {\n            \"type\": \"http\",\n            \"asgi\": {\"version\": \"3.0\"},\n            \"http_version\": \"1.1\",\n            \"method\": request.method,\n            \"headers\": [(k.lower(), v) for (k, v) in request.headers.raw],\n            \"scheme\": request.url.scheme,\n            \"path\": request.url.path,\n            \"raw_path\": request.url.raw_path,\n            \"query_string\": request.url.query,\n            \"server\": (request.url.host, request.url.port),\n            \"client\": self.client,\n            \"root_path\": self.root_path,\n        }\n\n        # Request.\n        request_body_chunks = request.stream.__aiter__()\n        request_complete = False\n\n        # Response.\n        status_code = None\n        response_headers = None\n        body_parts = []\n        response_started = False\n        response_complete = create_event()\n\n        # ASGI callables.\n\n        async def receive() -> typing.Dict[str, typing.Any]:\n            nonlocal request_complete\n\n            if request_complete:\n                await response_complete.wait()\n                return {\"type\": \"http.disconnect\"}\n\n            try:\n                body = await request_body_chunks.__anext__()\n            except StopAsyncIteration:\n                request_complete = True\n                return {\"type\": \"http.request\", \"body\": b\"\", \"more_body\": False}\n            return {\"type\": \"http.request\", \"body\": body, \"more_body\": True}\n\n        async def send(message: typing.Dict[str, typing.Any]) -> None:\n            nonlocal status_code, response_headers, response_started\n\n            if message[\"type\"] == \"http.response.start\":\n                assert not response_started\n\n                status_code = message[\"status\"]\n                response_headers = message.get(\"headers\", [])\n                response_started = True\n\n            elif message[\"type\"] == \"http.response.body\":\n                assert not response_complete.is_set()\n                body = message.get(\"body\", b\"\")\n                more_body = message.get(\"more_body\", False)\n\n                if body and request.method != \"HEAD\":\n                    body_parts.append(body)\n\n                if not more_body:\n                    response_complete.set()\n\n        try:\n            await self.app(scope, receive, send)\n        except Exception:  # noqa: PIE-786\n            if self.raise_app_exceptions:\n                raise\n\n            response_complete.set()\n            if status_code is None:\n                status_code = 500\n            if response_headers is None:\n                response_headers = {}\n\n        assert response_complete.is_set()\n        assert status_code is not None\n        assert response_headers is not None\n\n        stream = ASGIResponseStream(body_parts)\n\n        return Response(status_code, headers=response_headers, stream=stream)\n", "path": "httpx/_transports/asgi.py"}], "after_files": [{"content": "import typing\n\nimport sniffio\n\nfrom .._models import Request, Response\nfrom .._types import AsyncByteStream\nfrom .base import AsyncBaseTransport\n\nif typing.TYPE_CHECKING:  # pragma: no cover\n    import asyncio\n\n    import trio\n\n    Event = typing.Union[asyncio.Event, trio.Event]\n\n\n_Message = typing.Dict[str, typing.Any]\n_Receive = typing.Callable[[], typing.Awaitable[_Message]]\n_Send = typing.Callable[\n    [typing.Dict[str, typing.Any]], typing.Coroutine[None, None, None]\n]\n_ASGIApp = typing.Callable[\n    [typing.Dict[str, typing.Any], _Receive, _Send], typing.Coroutine[None, None, None]\n]\n\n\ndef create_event() -> \"Event\":\n    if sniffio.current_async_library() == \"trio\":\n        import trio\n\n        return trio.Event()\n    else:\n        import asyncio\n\n        return asyncio.Event()\n\n\nclass ASGIResponseStream(AsyncByteStream):\n    def __init__(self, body: typing.List[bytes]) -> None:\n        self._body = body\n\n    async def __aiter__(self) -> typing.AsyncIterator[bytes]:\n        yield b\"\".join(self._body)\n\n\nclass ASGITransport(AsyncBaseTransport):\n    \"\"\"\n    A custom AsyncTransport that handles sending requests directly to an ASGI app.\n    The simplest way to use this functionality is to use the `app` argument.\n\n    ```\n    client = httpx.AsyncClient(app=app)\n    ```\n\n    Alternatively, you can setup the transport instance explicitly.\n    This allows you to include any additional configuration arguments specific\n    to the ASGITransport class:\n\n    ```\n    transport = httpx.ASGITransport(\n        app=app,\n        root_path=\"/submount\",\n        client=(\"1.2.3.4\", 123)\n    )\n    client = httpx.AsyncClient(transport=transport)\n    ```\n\n    Arguments:\n\n    * `app` - The ASGI application.\n    * `raise_app_exceptions` - Boolean indicating if exceptions in the application\n       should be raised. Default to `True`. Can be set to `False` for use cases\n       such as testing the content of a client 500 response.\n    * `root_path` - The root path on which the ASGI application should be mounted.\n    * `client` - A two-tuple indicating the client IP and port of incoming requests.\n    ```\n    \"\"\"\n\n    def __init__(\n        self,\n        app: _ASGIApp,\n        raise_app_exceptions: bool = True,\n        root_path: str = \"\",\n        client: typing.Tuple[str, int] = (\"127.0.0.1\", 123),\n    ) -> None:\n        self.app = app\n        self.raise_app_exceptions = raise_app_exceptions\n        self.root_path = root_path\n        self.client = client\n\n    async def handle_async_request(\n        self,\n        request: Request,\n    ) -> Response:\n        assert isinstance(request.stream, AsyncByteStream)\n\n        # ASGI scope.\n        scope = {\n            \"type\": \"http\",\n            \"asgi\": {\"version\": \"3.0\"},\n            \"http_version\": \"1.1\",\n            \"method\": request.method,\n            \"headers\": [(k.lower(), v) for (k, v) in request.headers.raw],\n            \"scheme\": request.url.scheme,\n            \"path\": request.url.path,\n            \"raw_path\": request.url.raw_path.split(b\"?\")[0],\n            \"query_string\": request.url.query,\n            \"server\": (request.url.host, request.url.port),\n            \"client\": self.client,\n            \"root_path\": self.root_path,\n        }\n\n        # Request.\n        request_body_chunks = request.stream.__aiter__()\n        request_complete = False\n\n        # Response.\n        status_code = None\n        response_headers = None\n        body_parts = []\n        response_started = False\n        response_complete = create_event()\n\n        # ASGI callables.\n\n        async def receive() -> typing.Dict[str, typing.Any]:\n            nonlocal request_complete\n\n            if request_complete:\n                await response_complete.wait()\n                return {\"type\": \"http.disconnect\"}\n\n            try:\n                body = await request_body_chunks.__anext__()\n            except StopAsyncIteration:\n                request_complete = True\n                return {\"type\": \"http.request\", \"body\": b\"\", \"more_body\": False}\n            return {\"type\": \"http.request\", \"body\": body, \"more_body\": True}\n\n        async def send(message: typing.Dict[str, typing.Any]) -> None:\n            nonlocal status_code, response_headers, response_started\n\n            if message[\"type\"] == \"http.response.start\":\n                assert not response_started\n\n                status_code = message[\"status\"]\n                response_headers = message.get(\"headers\", [])\n                response_started = True\n\n            elif message[\"type\"] == \"http.response.body\":\n                assert not response_complete.is_set()\n                body = message.get(\"body\", b\"\")\n                more_body = message.get(\"more_body\", False)\n\n                if body and request.method != \"HEAD\":\n                    body_parts.append(body)\n\n                if not more_body:\n                    response_complete.set()\n\n        try:\n            await self.app(scope, receive, send)\n        except Exception:  # noqa: PIE-786\n            if self.raise_app_exceptions:\n                raise\n\n            response_complete.set()\n            if status_code is None:\n                status_code = 500\n            if response_headers is None:\n                response_headers = {}\n\n        assert response_complete.is_set()\n        assert status_code is not None\n        assert response_headers is not None\n\n        stream = ASGIResponseStream(body_parts)\n\n        return Response(status_code, headers=response_headers, stream=stream)\n", "path": "httpx/_transports/asgi.py"}]}