prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Session cookie should use root path
  The session cookie currently uses '/'.
  It should really use the ASGI root path instead, in case the application is submounted.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `starlette/middleware/sessions.py`
  Content:
  ```
  1 import json
  2 import typing
  3 from base64 import b64decode, b64encode
  4 
  5 import itsdangerous
  6 from itsdangerous.exc import BadTimeSignature, SignatureExpired
  7 
  8 from starlette.datastructures import MutableHeaders, Secret
  9 from starlette.requests import HTTPConnection
  10 from starlette.types import ASGIApp, Message, Receive, Scope, Send
  11 
  12 
  13 class SessionMiddleware:
  14     def __init__(
  15         self,
  16         app: ASGIApp,
  17         secret_key: typing.Union[str, Secret],
  18         session_cookie: str = "session",
  19         max_age: int = 14 * 24 * 60 * 60,  # 14 days, in seconds
  20         same_site: str = "lax",
  21         https_only: bool = False,
  22     ) -> None:
  23         self.app = app
  24         self.signer = itsdangerous.TimestampSigner(str(secret_key))
  25         self.session_cookie = session_cookie
  26         self.max_age = max_age
  27         self.security_flags = "httponly; samesite=" + same_site
  28         if https_only:  # Secure flag can be used with HTTPS only
  29             self.security_flags += "; secure"
  30 
  31     async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
  32         if scope["type"] not in ("http", "websocket"):  # pragma: no cover
  33             await self.app(scope, receive, send)
  34             return
  35 
  36         connection = HTTPConnection(scope)
  37         initial_session_was_empty = True
  38 
  39         if self.session_cookie in connection.cookies:
  40             data = connection.cookies[self.session_cookie].encode("utf-8")
  41             try:
  42                 data = self.signer.unsign(data, max_age=self.max_age)
  43                 scope["session"] = json.loads(b64decode(data))
  44                 initial_session_was_empty = False
  45             except (BadTimeSignature, SignatureExpired):
  46                 scope["session"] = {}
  47         else:
  48             scope["session"] = {}
  49 
  50         async def send_wrapper(message: Message) -> None:
  51             if message["type"] == "http.response.start":
  52                 if scope["session"]:
  53                     # We have session data to persist.
  54                     data = b64encode(json.dumps(scope["session"]).encode("utf-8"))
  55                     data = self.signer.sign(data)
  56                     headers = MutableHeaders(scope=message)
  57                     header_value = "%s=%s; path=/; Max-Age=%d; %s" % (
  58                         self.session_cookie,
  59                         data.decode("utf-8"),
  60                         self.max_age,
  61                         self.security_flags,
  62                     )
  63                     headers.append("Set-Cookie", header_value)
  64                 elif not initial_session_was_empty:
  65                     # The session has been cleared.
  66                     headers = MutableHeaders(scope=message)
  67                     header_value = "{}={}; {}".format(
  68                         self.session_cookie,
  69                         "null; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;",
  70                         self.security_flags,
  71                     )
  72                     headers.append("Set-Cookie", header_value)
  73             await send(message)
  74 
  75         await self.app(scope, receive, send_wrapper)
  76
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/starlette/middleware/sessions.py b/starlette/middleware/sessions.py
  --- a/starlette/middleware/sessions.py
  +++ b/starlette/middleware/sessions.py
  @@ -49,14 +49,16 @@
   
           async def send_wrapper(message: Message) -> None:
               if message["type"] == "http.response.start":
  +                path = scope.get("root_path", "") or "/"
                   if scope["session"]:
                       # We have session data to persist.
                       data = b64encode(json.dumps(scope["session"]).encode("utf-8"))
                       data = self.signer.sign(data)
                       headers = MutableHeaders(scope=message)
  -                    header_value = "%s=%s; path=/; Max-Age=%d; %s" % (
  +                    header_value = "%s=%s; path=%s; Max-Age=%d; %s" % (
                           self.session_cookie,
                           data.decode("utf-8"),
  +                        path,
                           self.max_age,
                           self.security_flags,
                       )
  @@ -66,7 +68,7 @@
                       headers = MutableHeaders(scope=message)
                       header_value = "{}={}; {}".format(
                           self.session_cookie,
  -                        "null; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;",
  +                        f"null; path={path}; expires=Thu, 01 Jan 1970 00:00:00 GMT;",
                           self.security_flags,
                       )
                       headers.append("Set-Cookie", header_value)
  
verification_info: {"golden_diff": "diff --git a/starlette/middleware/sessions.py b/starlette/middleware/sessions.py\n--- a/starlette/middleware/sessions.py\n+++ b/starlette/middleware/sessions.py\n@@ -49,14 +49,16 @@\n \n         async def send_wrapper(message: Message) -> None:\n             if message[\"type\"] == \"http.response.start\":\n+                path = scope.get(\"root_path\", \"\") or \"/\"\n                 if scope[\"session\"]:\n                     # We have session data to persist.\n                     data = b64encode(json.dumps(scope[\"session\"]).encode(\"utf-8\"))\n                     data = self.signer.sign(data)\n                     headers = MutableHeaders(scope=message)\n-                    header_value = \"%s=%s; path=/; Max-Age=%d; %s\" % (\n+                    header_value = \"%s=%s; path=%s; Max-Age=%d; %s\" % (\n                         self.session_cookie,\n                         data.decode(\"utf-8\"),\n+                        path,\n                         self.max_age,\n                         self.security_flags,\n                     )\n@@ -66,7 +68,7 @@\n                     headers = MutableHeaders(scope=message)\n                     header_value = \"{}={}; {}\".format(\n                         self.session_cookie,\n-                        \"null; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;\",\n+                        f\"null; path={path}; expires=Thu, 01 Jan 1970 00:00:00 GMT;\",\n                         self.security_flags,\n                     )\n                     headers.append(\"Set-Cookie\", header_value)\n", "issue": "Session cookie should use root path\nThe session cookie currently uses '/'.\r\nIt should really use the ASGI root path instead, in case the application is submounted.\n", "before_files": [{"content": "import json\nimport typing\nfrom base64 import b64decode, b64encode\n\nimport itsdangerous\nfrom itsdangerous.exc import BadTimeSignature, SignatureExpired\n\nfrom starlette.datastructures import MutableHeaders, Secret\nfrom starlette.requests import HTTPConnection\nfrom starlette.types import ASGIApp, Message, Receive, Scope, Send\n\n\nclass SessionMiddleware:\n    def __init__(\n        self,\n        app: ASGIApp,\n        secret_key: typing.Union[str, Secret],\n        session_cookie: str = \"session\",\n        max_age: int = 14 * 24 * 60 * 60,  # 14 days, in seconds\n        same_site: str = \"lax\",\n        https_only: bool = False,\n    ) -> None:\n        self.app = app\n        self.signer = itsdangerous.TimestampSigner(str(secret_key))\n        self.session_cookie = session_cookie\n        self.max_age = max_age\n        self.security_flags = \"httponly; samesite=\" + same_site\n        if https_only:  # Secure flag can be used with HTTPS only\n            self.security_flags += \"; secure\"\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        if scope[\"type\"] not in (\"http\", \"websocket\"):  # pragma: no cover\n            await self.app(scope, receive, send)\n            return\n\n        connection = HTTPConnection(scope)\n        initial_session_was_empty = True\n\n        if self.session_cookie in connection.cookies:\n            data = connection.cookies[self.session_cookie].encode(\"utf-8\")\n            try:\n                data = self.signer.unsign(data, max_age=self.max_age)\n                scope[\"session\"] = json.loads(b64decode(data))\n                initial_session_was_empty = False\n            except (BadTimeSignature, SignatureExpired):\n                scope[\"session\"] = {}\n        else:\n            scope[\"session\"] = {}\n\n        async def send_wrapper(message: Message) -> None:\n            if message[\"type\"] == \"http.response.start\":\n                if scope[\"session\"]:\n                    # We have session data to persist.\n                    data = b64encode(json.dumps(scope[\"session\"]).encode(\"utf-8\"))\n                    data = self.signer.sign(data)\n                    headers = MutableHeaders(scope=message)\n                    header_value = \"%s=%s; path=/; Max-Age=%d; %s\" % (\n                        self.session_cookie,\n                        data.decode(\"utf-8\"),\n                        self.max_age,\n                        self.security_flags,\n                    )\n                    headers.append(\"Set-Cookie\", header_value)\n                elif not initial_session_was_empty:\n                    # The session has been cleared.\n                    headers = MutableHeaders(scope=message)\n                    header_value = \"{}={}; {}\".format(\n                        self.session_cookie,\n                        \"null; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;\",\n                        self.security_flags,\n                    )\n                    headers.append(\"Set-Cookie\", header_value)\n            await send(message)\n\n        await self.app(scope, receive, send_wrapper)\n", "path": "starlette/middleware/sessions.py"}], "after_files": [{"content": "import json\nimport typing\nfrom base64 import b64decode, b64encode\n\nimport itsdangerous\nfrom itsdangerous.exc import BadTimeSignature, SignatureExpired\n\nfrom starlette.datastructures import MutableHeaders, Secret\nfrom starlette.requests import HTTPConnection\nfrom starlette.types import ASGIApp, Message, Receive, Scope, Send\n\n\nclass SessionMiddleware:\n    def __init__(\n        self,\n        app: ASGIApp,\n        secret_key: typing.Union[str, Secret],\n        session_cookie: str = \"session\",\n        max_age: int = 14 * 24 * 60 * 60,  # 14 days, in seconds\n        same_site: str = \"lax\",\n        https_only: bool = False,\n    ) -> None:\n        self.app = app\n        self.signer = itsdangerous.TimestampSigner(str(secret_key))\n        self.session_cookie = session_cookie\n        self.max_age = max_age\n        self.security_flags = \"httponly; samesite=\" + same_site\n        if https_only:  # Secure flag can be used with HTTPS only\n            self.security_flags += \"; secure\"\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        if scope[\"type\"] not in (\"http\", \"websocket\"):  # pragma: no cover\n            await self.app(scope, receive, send)\n            return\n\n        connection = HTTPConnection(scope)\n        initial_session_was_empty = True\n\n        if self.session_cookie in connection.cookies:\n            data = connection.cookies[self.session_cookie].encode(\"utf-8\")\n            try:\n                data = self.signer.unsign(data, max_age=self.max_age)\n                scope[\"session\"] = json.loads(b64decode(data))\n                initial_session_was_empty = False\n            except (BadTimeSignature, SignatureExpired):\n                scope[\"session\"] = {}\n        else:\n            scope[\"session\"] = {}\n\n        async def send_wrapper(message: Message) -> None:\n            if message[\"type\"] == \"http.response.start\":\n                path = scope.get(\"root_path\", \"\") or \"/\"\n                if scope[\"session\"]:\n                    # We have session data to persist.\n                    data = b64encode(json.dumps(scope[\"session\"]).encode(\"utf-8\"))\n                    data = self.signer.sign(data)\n                    headers = MutableHeaders(scope=message)\n                    header_value = \"%s=%s; path=%s; Max-Age=%d; %s\" % (\n                        self.session_cookie,\n                        data.decode(\"utf-8\"),\n                        path,\n                        self.max_age,\n                        self.security_flags,\n                    )\n                    headers.append(\"Set-Cookie\", header_value)\n                elif not initial_session_was_empty:\n                    # The session has been cleared.\n                    headers = MutableHeaders(scope=message)\n                    header_value = \"{}={}; {}\".format(\n                        self.session_cookie,\n                        f\"null; path={path}; expires=Thu, 01 Jan 1970 00:00:00 GMT;\",\n                        self.security_flags,\n                    )\n                    headers.append(\"Set-Cookie\", header_value)\n            await send(message)\n\n        await self.app(scope, receive, send_wrapper)\n", "path": "starlette/middleware/sessions.py"}]}