gradio: UI not displaying correctly because of path to `theme.css`

Describe the bug

The UI displays correctly on the local system. But when I upload it to the server, the UI CSS is not present.

Is there an existing issue for this?

  • I have searched the existing issues

Reproduction

 NA

Screenshot

Screenshot 2023-03-15 at 12 23 45 AM

Logs

No logs. Only a 404 error.

System Info

This is hosted on railway.app.

Severity

annoying

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 7
  • Comments: 50 (13 by maintainers)

Most upvoted comments

to reproduce this issue: app.py

from fastapi import FastAPI
import gradio as gr
import uvicorn

app = FastAPI()

@app.get('/')
def hello():
    return {"message":"hello"}

g_app = gr.Interface(
    lambda x: f"Hello {x}",
    "textbox",
    "textbox",
)

app = gr.mount_gradio_app(app, g_app, path="/gradio")

uvicorn.run(app,host="0.0.0.0",port=7860)

nginx conf

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    location /app/ {
        proxy_pass http://127.0.0.1:7860/;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

access the url http://localhost/app/gradio/ in browser image expected request url: http://localhost/app/gradio/theme.css

OS and package version info: gradio 3.28.3 fastapi 0.94.1 uvicorn 0.21.0 python: 3.10.6 OS: Linux Mint 21 nginx version: nginx/1.18.0 (Ubuntu)

It seems that the problem is still there for me:

app = FastAPI()
demo = gr.Interface(fn=fun, inputs=gr.Image(type="pil"), outputs="image")
setup_cors(app)
app = gr.mount_gradio_app(app, demo, path="/")
uvicorn.run(app, host=SERVER_NAME, port=SERVER_PORT)

This creates my app under 127.0.0.1:7860

BUT I do a ssh reverse tunnel toward another server that exposes the app to the web using nginx (the config is correct there) on the other server I access the app using http://www.domain.com/subpath/

The main file is loaded, the theme however is not. From the analysis of the network, the app tries to load http://www.domain.com/theme.css

If I put path="/subpath",

I can access the application only under http://www.domain.com/subpath/subpath but the theme.css is still not loaded… (as the theme is now under http://www.domain.com/subpath/subpath/theme.css but the app still look for http://www.domain.com/subpath/theme.css …)

I checked on the server, the css is there, but not in the folder the code is expecting it !

The code looks for http://www.domain.com/theme.css while the theme is actually in http://www.domain.com/subpath/theme.css

And I can’t change this behavior.

I also tryied to create static assets

def configure_static(app): 
    app.mount("/static", StaticFiles(directory="static"), name="static")

and put the theme.css there, but I can’t change gradio behavior to use the static assets folder.

I saw the addition of the root_path Gradio option to “solve” this, but everything worked fine before even when adding a path component using the rev proxy. Adding an explicit dependency on the route like this should be unnecessary and an added problem for deployment as you can’t change the host or nginx config without re-configuring the app, which might be running on another host even.

What is specific about the theme.css URL generation compared to all the other URL generations which all work fine?

We’ve been looking into this issue with @aliabid94 but are having a hard time reproducing it. Would you or someone facing this issue be able to share a minimal step-by-step process of how to reproduce this issue on a fresh EC2 instance?

Yes latest version. It works with v3.20.0 but not with any version after. So i think the bug was introduced when you guys added the custom theme support in v3.21.0

As mentioned in the linked Bug-report over at the stable-diffusion-webui, I managed to solve this by using the --subpath option to the webui. It sets the root_config option in Gradio that then generates the correct URL for theme.css

However I still don’t know why this solution was needed. Gradio correctly loads all the other dependencies without knowing this root prefix explicitly. Why is the theme.css special?

The proxied URL is available in window.location.pathname so that could have been used, or you could generate theme.css without any leading absolute path or / and just let the browser handle the URL generation. I assume this is how all the other assets load?

@abidlabs Thank you so much for finally fixing it! I’d like to add that it works not only on the two approaches, but also on a third approach using mount instead of root_path, which works as following:

# app.py
from fastapi import FastAPI
from subapp import subapp

app = FastAPI()
app.mount("/subapp", subapp)


# subapp.py
from fastapi import FastAPI
import gradio as gr

subapp = FastAPI()

@subapp.get('/')
def hello():
    return {"message":"hello"}

g_app = gr.Interface(
    lambda x: f"Hello {x}",
    "textbox",
    "textbox",
)
gr.mount_gradio_app(subapp, g_app, path="/gradio")

# now gradio app works at route /subapp/gradio, and hello api works at /subapp/

I believe we have a fix for this in https://github.com/gradio-app/gradio/pull/4133

If anyone could test this out, it would be extremely helpful! To test it out, you must:

  • Install gradio like this:

pip install https://gradio-builds.s3.amazonaws.com/1348f7ee48c10cdbd316dfab63c32988fed98e04/gradio-3.29.0-py3-none-any.whl

  • When you launch Gradio, you specify the subpath in the launch() method by using the root_path parameter. Or, if you are launching from within a FastAPI app, you can use the root_path parameter in the FastAPI class. So in @HUGHNew’s example, it would be:
app = FastAPI(root_path="/app")

@abidlabs @aliabid94 Please make sure the frontend typescript fix not only the theme.css missing problem under the path redirect situation.

The real predict post request should be fixed too…, otherwise the predict request will still failed

because it was routed to http://mydomain.com/run/predcit, while it should be routed to http://mydomain.com/gradio/run/predict

Hi, I’m having a similar problem.

Gradio app is deployed on EC2 instance via docker image. The container is running on port 7865. Accessing the app directly via the port works fine: http://domain.name:7865.

The problem occurs only when redirecting with nginx:

location /gradio/ {
                proxy_pass http://localhost:7865/;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

Then accessing http://domain.name/gradio will return blank gradio page - because of theme.css 404 error. It is looking for the file under the root path instead of the sub-route gradio.

For now what solved it for me was to redirect from the root path to the radio app, then it can find the theme.css file. Like this:

location / {
                proxy_pass http://localhost:7865/;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

But this issue should be fixed…

UPDATE - TEMP FIX

Mounting the gradio app to a fastapi app and adding the redirect response from the root of the fastapi app, together with the nginx redirect from subroute to the port fastapi app is running on - solved the themes.css 404 issue.

Here are the code changes for the app.py file:

from fastapi import FastAPI
from fastapi.responses import RedirectResponse
import gradio as gr

fastapi_app = FastAPI()
gradio_app = gr.Interface(lambda x: "Hello, " + x + "!", "textbox", "textbox")

@fastapi_app.get("/")
def redirect_to_gradio():
    return RedirectResponse(url="/gradio")

app = gr.mount_gradio_app(fastapi_app, gradio_app, path='/gradio')

I have the same problem with the gradio version 4.21, using mount_gradio_app with FastAPI. It loads all components of the web app correctly, except:

  • /favicon.ico
  • /assets/index-138adf03.css
  • /info
  • /theme.css

Gradio tries to load these from the root of the server instead of the path given in mount_gradio_app.

See a screenshot of the requests below. Loading from the root triggers and fails an authentication attempt, which is what you can see in the red entries.

image

The server is running on a machine managed by runai.

Interestingly, the exact same code works correctly on a different server that is not managed by runai, where these 4 files are loaded correctly from the path given in mount_gradio_app. But it would also correctly work on runai if Gradio would not decide to load these 4 files from the server root, so I do not understand why Gradio tries to load these 4 files from the root in the runai machine, but not on the other server.

Update: I found that it works better with version 4.20.1, where only the following two files are loaded incorrectly from the root:

  • /favicon.ico
  • /assets/index-138adf03.css

(Both are not essential, so downgrading to 4.20.1 is a viable workaround for now.)

Hello,

I was unable to determine how to reverse proxy gradio to a path on the domain when embedding via web components. Embedding via iframe works just fine.

My gradio applet’s launch config is:

demo.launch(root_path="/gradio-app")

My nginx conf is:

    location /gradio-app/ {
        proxy_pass http://127.0.0.1:7860/; # Change this if your Gradio app will be running on a different port
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

So I would expect to see the gradio app at https://domain.com/gradio-app

And this works, but when I embed via web components, it shows a 204 for https://example.com/config

So for whatever reason it’s not respecting the root_path=/gradio-app arg in the launch() config when embedded via webComponents.

Embedding via iFrame works fine for my use case, but thought I’d bring it up.

Gradio Version: 3.35.2

Awesome @microdou!

I believe we have a fix for this in #4133

If anyone could test this out, it would be extremely helpful! To test it out, you must:

  • Install gradio like this:

pip install https://gradio-builds.s3.amazonaws.com/1348f7ee48c10cdbd316dfab63c32988fed98e04/gradio-3.29.0-py3-none-any.whl

  • When you launch Gradio, you specify the subpath in the launch() method by using the root_path parameter. Or, if you are launching from within a FastAPI app, you can use the root_path parameter in the FastAPI class. So in @HUGHNew’s example, it would be:
app = FastAPI(root_path="/app")

Thanks for quick response and your helpful work!!!

It seems work well on my machine in both ways.

app.py

# pure gradio
import gradio as gr

g_app = gr.Interface(
    lambda x: f"Hello {x}",
    "textbox",
    "textbox",
)

g_app.launch(root_path="/app")
# theme.css request url: http://localhost/app/theme.css

app.py

# use fastapi
from fastapi import FastAPI
import uvicorn
import gradio as gr

app = FastAPI(root_path="/app")

@app.get('/')
def hello():
    return {"message":"hello"}

g_app = gr.Interface(
    lambda x: f"Hello {x}",
    "textbox",
    "textbox",
)

app = gr.mount_gradio_app(app, g_app, path="/gradio")
uvicorn.run(app,host="0.0.0.0",port=7860)
# theme.css request url: http://localhost/app/gradio/theme.css

Express my gratitude again.

Thanks so much @HUGHNew! Will take a look

Still broken since 3.20.0 …

Confirmed this is broken on 3.24.1 and main (https://gradio-main-build.s3.amazonaws.com/ad50eaa63df55a7cbb6caab4fe635206a070bbe9/gradio-3.24.1-py3-none-any.whl)

Downgrading to 3.20.0 allow this to work again for me – Running in Sagemaker Studio Lab https://github.com/machinelearnear/use-gradio-streamlit-sagemaker-studiolab

Is this issue fixed?

Reopening the issue. @majedtaki @dbonattoj are you using the latest version of Gradio?