Repository: gradio-app/gradio

Issue:
mount_gradio_app causing reload loop
### Describe the bug

Hello. I'm trying to run some apps using mount_gradio_app. When I go to that page it loads perfectly, but is stuck in a reload loop. In the network tab of the console the `/app_id` call is being made every ~500ms, it succeeds, gets the same ID returned, but keeps going.

I have a simple page showing at `/` (`read_main`) and this works correctly. It is only the sub-APIs that have the reload-loop issue. 

Int eh example below `/` has no issues, but `/words` (and any other sub API I try) gets caught in this loop.

Any help greatly appreciated. This is for an internal demo that won't be accessible on the internet (But will be hosted in k8s on an internal VPN), so it doesn't need to be full prod ready. 

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Reproduction

Here's a simple version:

main.py:

```
#!/usr/bin/env python3
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
import gradio as gr
from utils.demos import Demos
import sys

app = FastAPI()

@app.get("/", response_class=HTMLResponse)
def read_main():
    return """
    <html>
        <head>
            <title>Demo</title>
        </head>
        <body>
            <div>Demo</div>
        </body>
    </html>
    """

io = gr.Interface(lambda x: "Hello, " + x + "!", "textbox", "textbox")
app = gr.mount_gradio_app(app, demos.get_words_layout(), path="/words")
```

`Dockerfile`
```
# Base Image
FROM python:latest
# set default environment variables
ENV PYTHONUNBUFFERED 1
ENV LANG C.UTF-8
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
        tesseract-ocr \
        libtesseract-dev \
        nginx \
        && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# install environment dependencies
COPY ./demos/requirements.txt ./
RUN pip3 install --upgrade pip
RUN pip install -r requirements.txt
RUN ["sh", "-c", "python -m spacy download en_core_web_lg"]

# create and set working directory
RUN mkdir /demos

WORKDIR /demos
COPY ./demos ./

EXPOSE 80
EXPOSE 3000
CMD ["sh", "-c", "service nginx start;uvicorn main:app"]
```


nginx 
```
server {
    listen 80 default_server;
    server_name myserver;

    location / {
        proxy_pass  http://127.0.0.1:8000;
        proxy_set_header Host $host;
    }
}
```

I'm running the app now with `uvicorn main:app` but I've tried lots of options, tried it programmatically with reload set explicitly to false, and through Gunicorn and a socket. None of these solve the problem.

### Screenshot

![image](https://user-images.githubusercontent.com/104974291/195054397-2bd3adbb-371e-4eab-b558-032d6634d548.png)


### Logs

```shell
Me -> ~/Development/demo -> docker run -p 80:80 -p 3000:3000 -it demo
Starting nginx: nginx.
root@9a8279a9c6cd:/demos# uvicorn main:app
2022-10-11 09:30:54,705 - utils.utils - INFO - log level: INFO
INFO:     Started server process [34]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     127.0.0.1:52834 - "GET / HTTP/1.0" 200 OK
INFO:     127.0.0.1:52836 - "GET /assets/index.e0c646e0.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52838 - "GET /assets/index.3364fc9e.css HTTP/1.0" 200 OK
INFO:     127.0.0.1:52840 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52842 - "GET /assets/index.da18b6d7.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52850 - "GET /assets/index.cc2d8162.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52854 - "GET /assets/index.7dc02e74.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52856 - "GET /assets/index.5fe10dd6.css HTTP/1.0" 200 OK
INFO:     127.0.0.1:52858 - "GET /assets/index.950ac012.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52862 - "GET /assets/styles.ed3b21b5.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52860 - "GET /assets/Column.6bd7c762.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52868 - "GET /assets/Image.1afdf52a.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52864 - "GET /assets/index.2082796c.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52866 - "GET /assets/BlockLabel.0f912175.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52874 - "GET /assets/Block.19cdfe29.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52872 - "GET /assets/Webcam.955b3879.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52870 - "GET /assets/Upload.c52ab777.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52876 - "GET /assets/ModifyUpload.50f1ed7a.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52878 - "GET /assets/Image.70947e40.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52880 - "GET /assets/index.77f8571c.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52884 - "GET /assets/index.adf51434.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52882 - "GET /assets/csv.27f5436c.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52886 - "GET /assets/dsv.7fe76a93.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52888 - "GET /assets/Model3D.b527a682.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52890 - "GET /assets/logo.1a7cafda.svg HTTP/1.0" 200 OK
INFO:     127.0.0.1:52892 - "GET /assets/index.7bbf77fc.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:52896 - "GET /file%3D/demos/utils/Samples/somethign.jpg HTTP/1.0" 200 OK
INFO:     127.0.0.1:52894 - "GET /file%3D/demos/utils/Samples/image-text.jpg HTTP/1.0" 200 OK
INFO:     127.0.0.1:52898 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52900 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52902 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52904 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52906 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52908 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52910 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52912 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52914 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52916 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52918 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52920 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52922 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52924 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52926 - "GET /app_id HTTP/1.0" 200 OK
INFO:     127.0.0.1:52928 - "GET /app_id HTTP/1.0" 200 OK


...continues forever


with trace:


TRACE:    127.0.0.1:53350 - ASGI [45] Send {'type': 'http.response.start', 'status': 200, 'headers': '<...>'}
INFO:     127.0.0.1:53350 - "GET /app_id HTTP/1.0" 200 OK
TRACE:    127.0.0.1:53350 - ASGI [45] Send {'type': 'http.response.body', 'body': '<30 bytes>'}
TRACE:    127.0.0.1:53350 - ASGI [45] Completed
TRACE:    127.0.0.1:53350 - HTTP connection lost
TRACE:    127.0.0.1:53352 - HTTP connection made
TRACE:    127.0.0.1:53352 - ASGI [46] Started scope={'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.0', 'server': ('127.0.0.1', 8000), 'client': ('127.0.0.1', 53352), 'scheme': 'http', 'method': 'GET', 'root_path': '', 'path': '/words/app_id', 'raw_path': b'/words/app_id', 'query_string': b'', 'headers': '<...>'}
TRACE:    127.0.0.1:53352 - ASGI [46] Send {'type': 'http.response.start', 'status': 200, 'headers': '<...>'}
INFO:     127.0.0.1:53352 - "GET /app_id HTTP/1.0" 200 OK
TRACE:    127.0.0.1:53352 - ASGI [46] Send {'type': 'http.response.body', 'body': '<30 bytes>'}
TRACE:    127.0.0.1:53352 - ASGI [46] Completed
TRACE:    127.0.0.1:53352 - HTTP connection lost
TRACE:    127.0.0.1:53354 - HTTP connection made
TRACE:    127.0.0.1:53354 - ASGI [47] Started scope={'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.0', 'server': ('127.0.0.1', 8000), 'client': ('127.0.0.1', 53354), 'scheme': 'http', 'method': 'GET', 'root_path': '', 'path': '/words/app_id', 'raw_path': b'/words/app_id', 'query_string': b'', 'headers': '<...>'}
TRACE:    127.0.0.1:53354 - ASGI [47] Send {'type': 'http.response.start', 'status': 200, 'headers': '<...>'}
INFO:     127.0.0.1:53354 - "GET /app_id HTTP/1.0" 200 OK
TRACE:    127.0.0.1:53354 - ASGI [47] Send {'type': 'http.response.body', 'body': '<30 bytes>'}
TRACE:    127.0.0.1:53354 - ASGI [47] Completed
TRACE:    127.0.0.1:53354 - HTTP connection lost
TRACE:    127.0.0.1:53356 - HTTP connection made
TRACE:    127.0.0.1:53356 - ASGI [48] Started scope={'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.0', 'server': ('127.0.0.1', 8000), 'client': ('127.0.0.1', 53356), 'scheme': 'http', 'method': 'GET', 'root_path': '', 'path': '/words/app_id', 'raw_path': b'/words/app_id', 'query_string': b'', 'headers': '<...>'}
TRACE:    127.0.0.1:53356 - ASGI [48] Send {'type': 'http.response.start', 'status': 200, 'headers': '<...>'}
INFO:     127.0.0.1:53356 - "GET /app_id HTTP/1.0" 200 OK
TRACE:    127.0.0.1:53356 - ASGI [48] Send {'type': 'http.response.body', 'body': '<30 bytes>'}
TRACE:    127.0.0.1:53356 - ASGI [48] Completed
TRACE:    127.0.0.1:53356 - HTTP connection lost
TRACE:    127.0.0.1:53358 - HTTP connection made
TRACE:    127.0.0.1:53358 - ASGI [49] Started scope={'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.0', 'server': ('127.0.0.1', 8000), 'client': ('127.0.0.1', 53358), 'scheme': 'http', 'method': 'GET', 'root_path': '', 'path': '/words/app_id', 'raw_path': b'/words/app_id', 'query_string': b'', 'headers': '<...>'}
TRACE:    127.0.0.1:53358 - ASGI [49] Send {'type': 'http.response.start', 'status': 200, 'headers': '<...>'}
INFO:     127.0.0.1:53358 - "GET /app_id HTTP/1.0" 200 OK
TRACE:    127.0.0.1:53358 - ASGI [49] Send {'type': 'http.response.body', 'body': '<30 bytes>'}
TRACE:    127.0.0.1:53358 - ASGI [49] Completed
TRACE:    127.0.0.1:53358 - HTTP connection lost
TRACE:    127.0.0.1:53360 - HTTP connection made
TRACE:    127.0.0.1:53360 - ASGI [50] Started scope={'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.0', 'server': ('127.0.0.1', 8000), 'client': ('127.0.0.1', 53360), 'scheme': 'http', 'method': 'GET', 'root_path': '', 'path': '/words/app_id', 'raw_path': b'/words/app_id', 'query_string': b'', 'headers': '<...>'}
TRACE:    127.0.0.1:53360 - ASGI [50] Send {'type': 'http.response.start', 'status': 200, 'headers': '<...>'}
INFO:     127.0.0.1:53360 - "GET /app_id HTTP/1.0" 200 OK
TRACE:    127.0.0.1:53360 - ASGI [50] Send {'type': 'http.response.body', 'body': '<30 bytes>'}
TRACE:    127.0.0.1:53360 - ASGI [50] Completed
TRACE:    127.0.0.1:53360 - HTTP connection lost
^CINFO:     Shutting down
INFO:     Waiting for application shutdown.
TRACE:    ASGI [1] Receive {'type': 'lifespan.shutdown'}
TRACE:    ASGI [1] Send {'type': 'lifespan.shutdown.complete'}
TRACE:    ASGI [1] Completed
INFO:     Application shutdown complete.
INFO:     Finished server process [53]

```
```


### System Info

```shell
Docker running on Mac, Dockerfile included above.
```


### Severity

blocking all usage of gradio


Discussion:
It also does this whenever you run `gradio run.py` ('dev' mode) which makes debugging network requests difficult. It doesn't not cause any issue but it doesn't impair the developer experience. It also doesn't reliably reload the page, so I'm not sure how useful it actually is.

The dev mode functionality should be implemented with websockets rather than polling in this manner.
To close this issue, I think we need to make sure `mount_gradio_app` sets the dev mode to False (currently set to True by default and set to [False](https://github.com/gradio-app/gradio/blob/main/gradio/blocks.py#L468) on `launch`).

Reimplementing dev mode to not reload the page should be left to another issue. 
Hey @freddyaboulton , thanks, I had just tracked it down when you commented. I agree with the suggested fix, especially since the behaviour is bizarre and difficult to track down. For now, some updates to the docs might also be helpful. Thanks again!

Resolving patch:
diff --git a/gradio/routes.py b/gradio/routes.py
--- a/gradio/routes.py
+++ b/gradio/routes.py
@@ -461,7 +461,8 @@ def read_main():
         app = gr.mount_gradio_app(app, io, path="/gradio")
         # Then run `uvicorn run:app` from the terminal and navigate to http://localhost:8000/gradio.
     """
-
+    blocks.dev_mode = False
+    blocks.config = blocks.get_config_file()
     gradio_app = App.create_app(blocks)
 
     @app.on_event("startup")


Test patch:
diff --git a/test/test_routes.py b/test/test_routes.py
--- a/test/test_routes.py
+++ b/test/test_routes.py
@@ -6,10 +6,12 @@
 from unittest.mock import patch
 
 import pytest
+import starlette.routing
 import websockets
 from fastapi import FastAPI
 from fastapi.testclient import TestClient
 
+import gradio
 from gradio import Blocks, Interface, Textbox, close_all, routes
 
 os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
@@ -260,5 +262,22 @@ def test_get_server_url_from_ws_url(ws_url, answer):
     assert routes.get_server_url_from_ws_url(ws_url) == answer
 
 
+def test_mount_gradio_app_set_dev_mode_false():
+    app = FastAPI()
+
+    @app.get("/")
+    def read_main():
+        return {"message": "Hello!"}
+
+    with gradio.Blocks() as blocks:
+        gradio.Textbox("Hello from gradio!")
+
+    app = routes.mount_gradio_app(app, blocks, path="/gradio")
+    gradio_fast_api = next(
+        route for route in app.routes if isinstance(route, starlette.routing.Mount)
+    )
+    assert not gradio_fast_api.app.blocks.dev_mode
+
+
 if __name__ == "__main__":
     unittest.main()