prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  When "upload_file_request_handler.py" returns 400 error, we can see session ID.
  # Summary
  
  We make application on Microsoft Azure App Service with streamlit.
  When we conducted a test of uploading file with `st.file_uploader`,  it returned 400 error and **session ID** as string.
  We checked your codes and noticed that we have 400 error, `streamlit/lib/streamlit/server/upload_file_request_handler.py`  returns error code 400, reason and session ID on line 126-128.
  This problem may lead to security incidents like XSS.
  Please check it.
  
  # Steps to reproduce
  
  Code snippet:
  
  ```
  import streamlit as st
  
  uploaded_file = st.file_uploader("uploading Excel files", type="xlsx", key="xlsx_up")
  if uploaded_file is not None:
       st.write("Success")
  
  ```
  How the error occurred cannot be provided due to confidentiality,
  
  ## Expected behavior:
  
  When we have 400 error, streamlit will return only error code and error reason without session ID.
  
  ## Actual behavior:
  
  When we have 400 error, streamlit returns error code and error reason with session ID
  Screenshots cannot be uploaded due to confidentiality.
  
  ## Is this a regression?
  
  That is, did this use to work the way you expected in the past?
  yes / no
  ⇒no
  
  # Debug info
  
  - Streamlit version: (get it with `$ streamlit version`)
  ⇒0.74.1
  - Python version: (get it with `$ python --version`)
  ⇒3.7
  - Using Conda? PipEnv? PyEnv? Pex?
  ⇒Pip
  - OS version:
  ⇒Linux
  - Browser version:
  ⇒Chrome 88.0.4324.150
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `lib/streamlit/web/server/upload_file_request_handler.py`
  Content:
  ```
  1 # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #     http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 from typing import Any, Callable, Dict, List
  16 
  17 import tornado.httputil
  18 import tornado.web
  19 
  20 from streamlit import config
  21 from streamlit.logger import get_logger
  22 from streamlit.runtime.memory_uploaded_file_manager import MemoryUploadedFileManager
  23 from streamlit.runtime.uploaded_file_manager import UploadedFileManager, UploadedFileRec
  24 from streamlit.web.server import routes, server_util
  25 
  26 LOGGER = get_logger(__name__)
  27 
  28 
  29 class UploadFileRequestHandler(tornado.web.RequestHandler):
  30     """Implements the POST /upload_file endpoint."""
  31 
  32     def initialize(
  33         self,
  34         file_mgr: MemoryUploadedFileManager,
  35         is_active_session: Callable[[str], bool],
  36     ):
  37         """
  38         Parameters
  39         ----------
  40         file_mgr : UploadedFileManager
  41             The server's singleton UploadedFileManager. All file uploads
  42             go here.
  43         is_active_session:
  44             A function that returns true if a session_id belongs to an active
  45             session.
  46         """
  47         self._file_mgr = file_mgr
  48         self._is_active_session = is_active_session
  49 
  50     def set_default_headers(self):
  51         self.set_header("Access-Control-Allow-Methods", "PUT, OPTIONS, DELETE")
  52         self.set_header("Access-Control-Allow-Headers", "Content-Type")
  53         if config.get_option("server.enableXsrfProtection"):
  54             self.set_header(
  55                 "Access-Control-Allow-Origin",
  56                 server_util.get_url(config.get_option("browser.serverAddress")),
  57             )
  58             self.set_header("Access-Control-Allow-Headers", "X-Xsrftoken, Content-Type")
  59             self.set_header("Vary", "Origin")
  60             self.set_header("Access-Control-Allow-Credentials", "true")
  61         elif routes.allow_cross_origin_requests():
  62             self.set_header("Access-Control-Allow-Origin", "*")
  63 
  64     def options(self, **kwargs):
  65         """/OPTIONS handler for preflight CORS checks.
  66 
  67         When a browser is making a CORS request, it may sometimes first
  68         send an OPTIONS request, to check whether the server understands the
  69         CORS protocol. This is optional, and doesn't happen for every request
  70         or in every browser. If an OPTIONS request does get sent, and is not
  71         then handled by the server, the browser will fail the underlying
  72         request.
  73 
  74         The proper way to handle this is to send a 204 response ("no content")
  75         with the CORS headers attached. (These headers are automatically added
  76         to every outgoing response, including OPTIONS responses,
  77         via set_default_headers().)
  78 
  79         See https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
  80         """
  81         self.set_status(204)
  82         self.finish()
  83 
  84     def put(self, **kwargs):
  85         """Receive an uploaded file and add it to our UploadedFileManager."""
  86 
  87         args: Dict[str, List[bytes]] = {}
  88         files: Dict[str, List[Any]] = {}
  89 
  90         session_id = self.path_kwargs["session_id"]
  91         file_id = self.path_kwargs["file_id"]
  92 
  93         tornado.httputil.parse_body_arguments(
  94             content_type=self.request.headers["Content-Type"],
  95             body=self.request.body,
  96             arguments=args,
  97             files=files,
  98         )
  99 
  100         try:
  101             if not self._is_active_session(session_id):
  102                 raise Exception(f"Invalid session_id: '{session_id}'")
  103         except Exception as e:
  104             self.send_error(400, reason=str(e))
  105             return
  106 
  107         uploaded_files: List[UploadedFileRec] = []
  108 
  109         for _, flist in files.items():
  110             for file in flist:
  111                 uploaded_files.append(
  112                     UploadedFileRec(
  113                         file_id=file_id,
  114                         name=file["filename"],
  115                         type=file["content_type"],
  116                         data=file["body"],
  117                     )
  118                 )
  119 
  120         if len(uploaded_files) != 1:
  121             self.send_error(
  122                 400, reason=f"Expected 1 file, but got {len(uploaded_files)}"
  123             )
  124             return
  125 
  126         self._file_mgr.add_file(session_id=session_id, file=uploaded_files[0])
  127         self.set_status(204)
  128 
  129     def delete(self, **kwargs):
  130         """Delete file request handler."""
  131         session_id = self.path_kwargs["session_id"]
  132         file_id = self.path_kwargs["file_id"]
  133 
  134         self._file_mgr.remove_file(session_id=session_id, file_id=file_id)
  135         self.set_status(204)
  136
  ```
  --- 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/lib/streamlit/web/server/upload_file_request_handler.py b/lib/streamlit/web/server/upload_file_request_handler.py
  --- a/lib/streamlit/web/server/upload_file_request_handler.py
  +++ b/lib/streamlit/web/server/upload_file_request_handler.py
  @@ -99,7 +99,7 @@
   
           try:
               if not self._is_active_session(session_id):
  -                raise Exception(f"Invalid session_id: '{session_id}'")
  +                raise Exception(f"Invalid session_id")
           except Exception as e:
               self.send_error(400, reason=str(e))
               return
  
verification_info: {"golden_diff": "diff --git a/lib/streamlit/web/server/upload_file_request_handler.py b/lib/streamlit/web/server/upload_file_request_handler.py\n--- a/lib/streamlit/web/server/upload_file_request_handler.py\n+++ b/lib/streamlit/web/server/upload_file_request_handler.py\n@@ -99,7 +99,7 @@\n \n         try:\n             if not self._is_active_session(session_id):\n-                raise Exception(f\"Invalid session_id: '{session_id}'\")\n+                raise Exception(f\"Invalid session_id\")\n         except Exception as e:\n             self.send_error(400, reason=str(e))\n             return\n", "issue": "When \"upload_file_request_handler.py\" returns 400 error, we can see session ID.\n# Summary\r\n\r\nWe make application on Microsoft Azure App Service with streamlit.\r\nWhen we conducted a test of uploading file with `st.file_uploader`,  it returned 400 error and **session ID** as string.\r\nWe checked your codes and noticed that we have 400 error, `streamlit/lib/streamlit/server/upload_file_request_handler.py`  returns error code 400, reason and session ID on line 126-128.\r\nThis problem may lead to security incidents like XSS.\r\nPlease check it.\r\n\r\n# Steps to reproduce\r\n\r\nCode snippet:\r\n\r\n```\r\nimport streamlit as st\r\n\r\nuploaded_file = st.file_uploader(\"uploading Excel files\", type=\"xlsx\", key=\"xlsx_up\")\r\nif uploaded_file is not None:\r\n     st.write(\"Success\")\r\n\r\n```\r\nHow the error occurred cannot be provided due to confidentiality,\r\n\r\n## Expected behavior:\r\n\r\nWhen we have 400 error, streamlit will return only error code and error reason without session ID.\r\n\r\n## Actual behavior:\r\n\r\nWhen we have 400 error, streamlit returns error code and error reason with session ID\r\nScreenshots cannot be uploaded due to confidentiality.\r\n\r\n## Is this a regression?\r\n\r\nThat is, did this use to work the way you expected in the past?\r\nyes / no\r\n\u21d2no\r\n\r\n# Debug info\r\n\r\n- Streamlit version: (get it with `$ streamlit version`)\r\n\u21d20.74.1\r\n- Python version: (get it with `$ python --version`)\r\n\u21d23.7\r\n- Using Conda? PipEnv? PyEnv? Pex?\r\n\u21d2Pip\r\n- OS version:\r\n\u21d2Linux\r\n- Browser version:\r\n\u21d2Chrome 88.0.4324.150\n", "before_files": [{"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom typing import Any, Callable, Dict, List\n\nimport tornado.httputil\nimport tornado.web\n\nfrom streamlit import config\nfrom streamlit.logger import get_logger\nfrom streamlit.runtime.memory_uploaded_file_manager import MemoryUploadedFileManager\nfrom streamlit.runtime.uploaded_file_manager import UploadedFileManager, UploadedFileRec\nfrom streamlit.web.server import routes, server_util\n\nLOGGER = get_logger(__name__)\n\n\nclass UploadFileRequestHandler(tornado.web.RequestHandler):\n    \"\"\"Implements the POST /upload_file endpoint.\"\"\"\n\n    def initialize(\n        self,\n        file_mgr: MemoryUploadedFileManager,\n        is_active_session: Callable[[str], bool],\n    ):\n        \"\"\"\n        Parameters\n        ----------\n        file_mgr : UploadedFileManager\n            The server's singleton UploadedFileManager. All file uploads\n            go here.\n        is_active_session:\n            A function that returns true if a session_id belongs to an active\n            session.\n        \"\"\"\n        self._file_mgr = file_mgr\n        self._is_active_session = is_active_session\n\n    def set_default_headers(self):\n        self.set_header(\"Access-Control-Allow-Methods\", \"PUT, OPTIONS, DELETE\")\n        self.set_header(\"Access-Control-Allow-Headers\", \"Content-Type\")\n        if config.get_option(\"server.enableXsrfProtection\"):\n            self.set_header(\n                \"Access-Control-Allow-Origin\",\n                server_util.get_url(config.get_option(\"browser.serverAddress\")),\n            )\n            self.set_header(\"Access-Control-Allow-Headers\", \"X-Xsrftoken, Content-Type\")\n            self.set_header(\"Vary\", \"Origin\")\n            self.set_header(\"Access-Control-Allow-Credentials\", \"true\")\n        elif routes.allow_cross_origin_requests():\n            self.set_header(\"Access-Control-Allow-Origin\", \"*\")\n\n    def options(self, **kwargs):\n        \"\"\"/OPTIONS handler for preflight CORS checks.\n\n        When a browser is making a CORS request, it may sometimes first\n        send an OPTIONS request, to check whether the server understands the\n        CORS protocol. This is optional, and doesn't happen for every request\n        or in every browser. If an OPTIONS request does get sent, and is not\n        then handled by the server, the browser will fail the underlying\n        request.\n\n        The proper way to handle this is to send a 204 response (\"no content\")\n        with the CORS headers attached. (These headers are automatically added\n        to every outgoing response, including OPTIONS responses,\n        via set_default_headers().)\n\n        See https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request\n        \"\"\"\n        self.set_status(204)\n        self.finish()\n\n    def put(self, **kwargs):\n        \"\"\"Receive an uploaded file and add it to our UploadedFileManager.\"\"\"\n\n        args: Dict[str, List[bytes]] = {}\n        files: Dict[str, List[Any]] = {}\n\n        session_id = self.path_kwargs[\"session_id\"]\n        file_id = self.path_kwargs[\"file_id\"]\n\n        tornado.httputil.parse_body_arguments(\n            content_type=self.request.headers[\"Content-Type\"],\n            body=self.request.body,\n            arguments=args,\n            files=files,\n        )\n\n        try:\n            if not self._is_active_session(session_id):\n                raise Exception(f\"Invalid session_id: '{session_id}'\")\n        except Exception as e:\n            self.send_error(400, reason=str(e))\n            return\n\n        uploaded_files: List[UploadedFileRec] = []\n\n        for _, flist in files.items():\n            for file in flist:\n                uploaded_files.append(\n                    UploadedFileRec(\n                        file_id=file_id,\n                        name=file[\"filename\"],\n                        type=file[\"content_type\"],\n                        data=file[\"body\"],\n                    )\n                )\n\n        if len(uploaded_files) != 1:\n            self.send_error(\n                400, reason=f\"Expected 1 file, but got {len(uploaded_files)}\"\n            )\n            return\n\n        self._file_mgr.add_file(session_id=session_id, file=uploaded_files[0])\n        self.set_status(204)\n\n    def delete(self, **kwargs):\n        \"\"\"Delete file request handler.\"\"\"\n        session_id = self.path_kwargs[\"session_id\"]\n        file_id = self.path_kwargs[\"file_id\"]\n\n        self._file_mgr.remove_file(session_id=session_id, file_id=file_id)\n        self.set_status(204)\n", "path": "lib/streamlit/web/server/upload_file_request_handler.py"}], "after_files": [{"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom typing import Any, Callable, Dict, List\n\nimport tornado.httputil\nimport tornado.web\n\nfrom streamlit import config\nfrom streamlit.logger import get_logger\nfrom streamlit.runtime.memory_uploaded_file_manager import MemoryUploadedFileManager\nfrom streamlit.runtime.uploaded_file_manager import UploadedFileManager, UploadedFileRec\nfrom streamlit.web.server import routes, server_util\n\nLOGGER = get_logger(__name__)\n\n\nclass UploadFileRequestHandler(tornado.web.RequestHandler):\n    \"\"\"Implements the POST /upload_file endpoint.\"\"\"\n\n    def initialize(\n        self,\n        file_mgr: MemoryUploadedFileManager,\n        is_active_session: Callable[[str], bool],\n    ):\n        \"\"\"\n        Parameters\n        ----------\n        file_mgr : UploadedFileManager\n            The server's singleton UploadedFileManager. All file uploads\n            go here.\n        is_active_session:\n            A function that returns true if a session_id belongs to an active\n            session.\n        \"\"\"\n        self._file_mgr = file_mgr\n        self._is_active_session = is_active_session\n\n    def set_default_headers(self):\n        self.set_header(\"Access-Control-Allow-Methods\", \"PUT, OPTIONS, DELETE\")\n        self.set_header(\"Access-Control-Allow-Headers\", \"Content-Type\")\n        if config.get_option(\"server.enableXsrfProtection\"):\n            self.set_header(\n                \"Access-Control-Allow-Origin\",\n                server_util.get_url(config.get_option(\"browser.serverAddress\")),\n            )\n            self.set_header(\"Access-Control-Allow-Headers\", \"X-Xsrftoken, Content-Type\")\n            self.set_header(\"Vary\", \"Origin\")\n            self.set_header(\"Access-Control-Allow-Credentials\", \"true\")\n        elif routes.allow_cross_origin_requests():\n            self.set_header(\"Access-Control-Allow-Origin\", \"*\")\n\n    def options(self, **kwargs):\n        \"\"\"/OPTIONS handler for preflight CORS checks.\n\n        When a browser is making a CORS request, it may sometimes first\n        send an OPTIONS request, to check whether the server understands the\n        CORS protocol. This is optional, and doesn't happen for every request\n        or in every browser. If an OPTIONS request does get sent, and is not\n        then handled by the server, the browser will fail the underlying\n        request.\n\n        The proper way to handle this is to send a 204 response (\"no content\")\n        with the CORS headers attached. (These headers are automatically added\n        to every outgoing response, including OPTIONS responses,\n        via set_default_headers().)\n\n        See https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request\n        \"\"\"\n        self.set_status(204)\n        self.finish()\n\n    def put(self, **kwargs):\n        \"\"\"Receive an uploaded file and add it to our UploadedFileManager.\"\"\"\n\n        args: Dict[str, List[bytes]] = {}\n        files: Dict[str, List[Any]] = {}\n\n        session_id = self.path_kwargs[\"session_id\"]\n        file_id = self.path_kwargs[\"file_id\"]\n\n        tornado.httputil.parse_body_arguments(\n            content_type=self.request.headers[\"Content-Type\"],\n            body=self.request.body,\n            arguments=args,\n            files=files,\n        )\n\n        try:\n            if not self._is_active_session(session_id):\n                raise Exception(f\"Invalid session_id\")\n        except Exception as e:\n            self.send_error(400, reason=str(e))\n            return\n\n        uploaded_files: List[UploadedFileRec] = []\n\n        for _, flist in files.items():\n            for file in flist:\n                uploaded_files.append(\n                    UploadedFileRec(\n                        file_id=file_id,\n                        name=file[\"filename\"],\n                        type=file[\"content_type\"],\n                        data=file[\"body\"],\n                    )\n                )\n\n        if len(uploaded_files) != 1:\n            self.send_error(\n                400, reason=f\"Expected 1 file, but got {len(uploaded_files)}\"\n            )\n            return\n\n        self._file_mgr.add_file(session_id=session_id, file=uploaded_files[0])\n        self.set_status(204)\n\n    def delete(self, **kwargs):\n        \"\"\"Delete file request handler.\"\"\"\n        session_id = self.path_kwargs[\"session_id\"]\n        file_id = self.path_kwargs[\"file_id\"]\n\n        self._file_mgr.remove_file(session_id=session_id, file_id=file_id)\n        self.set_status(204)\n", "path": "lib/streamlit/web/server/upload_file_request_handler.py"}]}