apache / apache/superset

bug(AppRootMiddleware): /static/ assets return 404 in subdirectory deployments (SUPERSET_APP_ROOT)

Open
#39,429 1 comment 0 reactions 1 assignee Assigned to @sadpandajoe View on GitHub
change:frontend
Dominant language
Python
Stars
74.8k
Forks
18.3k
Avg merge
2d 5h
Merged PRs (30d)
685

Description

### Bug description

When deploying Superset under a subpath using `SUPERSET_APP_ROOT` (e.g. `/dashboards`), all requests to `/static/` assets return **404**. This affects static assets such as the logo, CSS, and JS bundles — webpack compiles asset paths with a hardcoded `/static/assets/` publicPath that does **not** include the app root prefix.

### Root cause

`AppRootMiddleware.__call__` returns `NotFound()` for any request that does not start with `self.app_root`. Since webpack always generates `/static/assets/...` paths (without the app root prefix), these requests are blocked:

```python
# Current behavior — blocks /static/ requests
if original_path_info.startswith(self.app_root):
...
else:
return NotFound()(environ, start_response) # ← blocks /static/assets/*
```

### Steps to reproduce

1. Set `SUPERSET_APP_ROOT=/dashboards` (or any non-root value)
2. Configure a reverse proxy (nginx/Apache) with:
- `ProxyPass /dashboards http://localhost:8088/dashboards`
- `ProxyPass /static http://localhost:8088/static`
3. Open `https:///dashboards` in a browser
4. Observe 404 for `https:///static/assets/images/superset-logo-horiz.png`

### Expected behavior

Static assets under `/static/` should be served regardless of the configured app root, since webpack hardcodes `/static/assets/` as the publicPath at build time.

### Proposed fix

Add an `elif` branch to `AppRootMiddleware.__call__` to pass `/static/` requests through without stripping the app root:

```python
elif original_path_info.startswith("/static/"):
# Webpack compiles asset paths with hardcoded /static/assets/ publicPath.
# Pass these through without stripping the app root so static assets
# are served correctly in subdirectory deployments.
return self.wsgi_app(environ, start_response)
```

### Superset version

6.1.0rc1

### Python version

3.11

### Browser

Chrome

### Additional context

- PR #35098 fixed app icon and report URL paths for subdirectory deployments but did **not** address the `AppRootMiddleware` blocking of `/static/` requests.
- webpack `publicPath` is hardcoded to `/static/assets/` in `webpack.config.js` and cannot be changed at runtime.
- Related: #39431 — `service-worker.js` is missing from the production Docker image entirely (separate Dockerfile bug).

### Checklist

- [x] I have searched Superset docs and Slack and didn't find a solution to my problem.
- [x] I have searched the GitHub issue tracker and didn't find a similar bug report.
- [x] I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.