Skip to content

Static asset URLs use absolute host:port causing 404 when binding to 0.0.0.0 #28

Description

@sternma

Description

When running Textual-Serve bound to 0.0.0.0, the landing‐page template inlines all static asset URLs (CSS/JS/images) using the configured host or public_url. If you pass host="0.0.0.0" (or forget to set public_url), every request for /static/... goes to http://0.0.0.0:8000/static/..., which is not routable, and assets fail to load.

Steps to Reproduce

  1. Install textual-serve==1.1.2 in a project.
  2. Create a main.py containing:
    from textual_serve.server import Server
    
    server = Server("python3 your_app.py", host="0.0.0.0")
    server.serve(debug=True)
  3. Run:
    python3 main.py
  4. Open a browser to http://<your-machine-IP>:8000/.
  5. Observe in DevTools → Network that requests for xterm.css, textual.js, etc. are targeting http://0.0.0.0:8000/static/... and failing.

Actual Behavior

  • Asset requests are issued to 0.0.0.0:8000, which refuses connections.
  • Landing page shows placeholder panel without styling or “Run ▶︎” button (static assets never load).

Expected Behavior

Assets should either:

  1. Be served via relative URLs (e.g. /static/js/textual.js) so they load from the same origin the browser requested, or
  2. If an absolute URL is required, fall back to using the incoming Host header when public_url is unset, rather than the bind address.

Environment

  • textual-serve version: 1.1.2
  • Python: 3.10.11
  • Platform: Ubuntu 22.04 LTS (Docker container)
  • Browser: Chrome 135.0.0.0 on macOS 10.15.7

Proposed Solution

Update the Jinja template (app_index.html) so that static assets use relative paths by default:

<!-- before -->
<link rel="stylesheet" href="{{ config.static.root }}/css/xterm.css">

<!-- after -->
<link rel="stylesheet" href="/static/css/xterm.css">

Alternatively, detect when public_url is the generic bind address (0.0.0.0 or ::) and fall back to Host header–based URL generation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions