Skip to content

Add --root_app option to serve any app at / - #1070

Open
mkostrikin wants to merge 1 commit into
web2py:masterfrom
mkostrikin:root-app-option
Open

mkostrikin wants to merge 1 commit into
web2py:masterfrom
mkostrikin:root-app-option

Conversation

@mkostrikin

Copy link
Copy Markdown
Contributor

Summary

Right now only the app named _default can handle requests at /. Every other app is always mounted under /{app_name}/, and the usual workaround is to symlink apps/_default to the real app.

This PR adds a run option that picks which app is served at /:

py4web run --root_app myapp apps

The chosen app's actions and static files are then served without the /{app_name} prefix, and URL() builds links to match. The default is still _default, so existing setups behave exactly as before.

Changes

  • py4web/core.py
    • New --root_app option on run, defaulting to _default. Like the other run options, it is exported as PY4WEB_ROOT_APP, so it also works with wsgi(root_app=...) and reaches server workers.
    • New helpers get_root_app_name() / is_root_app(). They replace the hardcoded "_default" in five places: action route registration, static file routes, URL() (two places), and the lazy reloader hook.
    • When a non-default root app is chosen but isn't loaded, run prints a warning at startup.
  • Docs: --root_app is documented in chapter 3 (options listing, explanation, and the Default-app note, which no longer suggests the symlink) and in chapter 5 (routes without a prefix). The translated .po files are left for the regular translation update.
  • Tests: new tests/test_root_app.py with 12 tests covering name resolution, URL() prefixes, action and static route registration, the reloader fallback, the CLI option and environment export, and wsgi(root_app=...).

Behaviour notes

  • With --root_app todo, the _default app (if present) is served at /_default/ like any other app.
  • Links built with URL() adjust automatically. Paths hardcoded as /todo/... in templates or JS do not.
  • As with _default today, a route in the root app that has the same name as another app (e.g. _dashboard) collides with that app.

Testing

  • make test: 136 passed (the existing tests plus the 12 new ones).
  • Manual run with py4web run apps --root_app todo:
    • / serves todo, and its links point to /static/....
    • /static/js/utils.js returns 200.
    • /todo/ returns 404.
    • /_default/ still serves the default app.

🤖 Generated with Claude Code

Until now only the app named _default could handle requests at /;
every other app was always mounted under /{app_name}/. The usual
workaround was to symlink apps/_default to the real app.

`py4web run --root_app myapp apps` now chooses which app is mounted
at / (routes and static files without the /{app_name} prefix). The
value is exported as PY4WEB_ROOT_APP, so it also works with
wsgi(root_app=...) and reaches server workers. It defaults to
_default, so existing setups are unchanged; when another app is
chosen, _default is served at /_default/ like any other app.

- core: add get_root_app_name()/is_root_app() and use them in
  action route registration, static routes, URL() and the lazy
  reloader hook instead of the hardcoded "_default"
- run: warn at startup if the chosen root app is not loaded
- docs: document --root_app in chapter 3 and 5
- tests: add tests/test_root_app.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant