Skip to content

Add prefix path to API and WebUI#3007

Merged
danielaskdd merged 18 commits intoHKUDS:mainfrom
shahrin014:main
May 8, 2026
Merged

Add prefix path to API and WebUI#3007
danielaskdd merged 18 commits intoHKUDS:mainfrom
shahrin014:main

Conversation

@shahrin014
Copy link
Copy Markdown

Description

This PR adds configurable path prefixes for the LightRAG API and WebUI, allowing users to customize URL paths where the API and WebUI are mounted. This is useful for deployments behind reverse proxies or when integrating with existing infrastructure that requires specific path structures.

Related Issues

#2755

Changes Made

1. Configurable API Prefix (--api-prefix / LIGHTRAG_API_PREFIX)

  • Added CLI argument and environment variable support for customizing the API route prefix
  • Default: no prefix (root)
  • Updates frontend constants to read from VITE_API_PREFIX
  • All API routes (documents, query, graph, etc.) are now correctly prefixed
  • Fixed document routes mounting to avoid duplicate /documents/documents/ path
  • Fixed Swagger UI static files to be served at the prefixed path

2. Configurable WebUI Path (--webui-path / LIGHTRAG_WEBUI_PATH)

  • Added CLI argument and environment variable support for customizing the WebUI mount path
  • Default: /webui
  • Updates frontend build to use VITE_WEBUI_PREFIX for correct asset paths
  • WebUI is now accessible at the configured path

3. Tests

  • Added integration tests using TestClient that verify actual HTTP behavior
  • Removed superficial TestPrefixPathCalculation class that only tested string concatenation
  • Tests verify prefixed routes return 200 and unprefixed routes return 404

Test Results

Backend Tests (pytest)

710 passed, 37 skipped, 29 warnings in 41.76s


Path prefix specific tests:
tests/test_path_prefixes.py::TestAPIPrefixIntegration::test_routes_mounted_at_prefixed_paths PASSED tests/test_path_prefixes.py::TestAPIPrefixIntegration::test_document_routes_prefixed PASSED tests/test_path_prefixes.py::TestNoPrefixIntegration::test_routes_at_root_no_prefix PASSED tests/test_path_prefixes.py::TestWebUIPrefixIntegration::test_webui_at_prefixed_path PASSED tests/test_path_prefixes.py::TestWebUIPrefixIntegration::test_webui_not_at_unprefixed_path_with_prefix PASSED tests/test_path_prefixes.py::TestEnvironmentVariables::test_env_api_prefix PASSED tests/test_path_prefixes.py::TestEnvironmentVariables::test_env_webui_path PASSED

Frontend Tests (Bun)

3 pass, 0 fail, 13 expect() calls Ran 3 tests across 1 file. [623.00ms]

opencode added 6 commits April 30, 2026 04:14
- Add --api-prefix / LIGHTRAG_API_PREFIX for API routes (default: '')
- Add --webui-path / LIGHTRAG_WEBUI_PATH for WebUI mount (default: /webui)
- Update frontend constants to read from VITE_API_PREFIX and VITE_WEBUI_PREFIX
- Add unit tests using test prefixes: unit-test-back/api and unit-test-front/webui
- Document new env vars in env.example
The document router already has prefix='/documents' defined internally,
so including it with '/test-api/documents' resulted in double
'/documents/documents/' path. Now uses api_prefix directly.
Swagger UI static files were mounted at /static/swagger-ui without
the API prefix, causing 404 errors when accessing /docs with a
prefix. Now mounts at {api_prefix}/static/swagger-ui and updates
the HTML references accordingly.
The TestPrefixPathCalculation class only tested Python string
concatenation (f-strings), not actual FastAPI route mounting
or HTTP behavior. Removed in favor of keeping meaningful tests
that verify CLI parsing and environment variable reading.
Replace superficial tests that only checked argument parsing
with actual HTTP-level integration tests using TestClient.

Tests now verify:
- Routes are accessible at prefixed paths (e.g., /test-api/docs)
- Unprefixed paths return 404 when prefix is set
- Routes work at root when no prefix is set
- Document routes don't have duplicate /documents/documents/ path
Add tests to verify WebUI is served at the correct prefixed path:
- /test-webui/ returns 200 or 307 redirect
- /webui/ returns 404 when custom path is set
- Validates WebUI path configuration works correctly
@shahrin014
Copy link
Copy Markdown
Author

If there are better variable naming suggestions or alternative implementations please let me know.

@danielaskdd danielaskdd added enhancement New feature or request tracked Issue is tracked by project labels May 7, 2026
@danielaskdd
Copy link
Copy Markdown
Collaborator

Thanks for submitting this PR! Solving the reverse proxy and sub-path mounting issue is critical for LightRAG as it moves towards more mature, enterprise-grade containerized deployments. The architectural idea of using two environment variables to control the frontend and backend prefixes is very clear.

After carefully reviewing the code, I have some architectural suggestions regarding the backend implementation to further optimize this feature:

1. Frontend (WebUI) — Recommended to Keep

Injecting the VITE_WEBUI_PREFIX environment variable during the Vite build process is the standard industry practice for handling sub-path mounting in modern SPAs. This part of the code is excellent and successfully resolves the static asset routing issues. I highly recommend keeping this logic exactly as it is.

2. Backend (API) — Recommended to Refactor using root_path

Currently, the PR handles the backend API prefix by reading LIGHTRAG_API_PREFIX, manually appending it to every APIRouter, and modifying the static file paths for Swagger UI.

This current backend approach introduces a major pain point: It makes adding new routes highly error-prone.

  • High Code Invasiveness: The deployment configuration (where the app is mounted) is polluting the business logic. Every time a developer adds a new route in the future, they have to carefully remember to handle this prefix concatenation.
  • Prone to Routing Bugs: As you noticed and fixed with the /documents/documents/ bug, manual path string concatenation easily leads to unexpected nested routes.
  • Maintenance Overhead: Manually intercepting and modifying Swagger's static routing deviates from the framework's native behavior.

Final Recommendation:
For the backend, the Cloud Native best practice is strict decoupling of configuration and code. FastAPI (based on the ASGI spec) natively provides a parameter specifically designed for reverse proxy scenarios: root_path.

We should keep the LIGHTRAG_API_PREFIX environment variable as the configuration entry point, but I strongly suggest reverting all invasive modifications to the APIRouter and static directories, and instead passing the prefix globally when instantiating FastAPI:

import os
from fastapi import FastAPI

# 1. Continue reading the prefix from the environment variable
api_prefix = os.environ.get("LIGHTRAG_API_PREFIX", "")

# 2. Pass it to the root_path parameter ONLY when instantiating the app
app = FastAPI(
    title="LightRAG API",
    root_path=api_prefix  
)

# 3. Revert all routers to their pre-PR state (keep business logic pure)
# router = APIRouter(...) # NO need to manually pass prefix=api_prefix here
# app.include_router(documents_router) 

The massive advantages of the root_path approach:

  1. Zero Code Intrusion: All routers continue to work seamlessly at the root / level. The business logic remains completely unaware of the sub-path it is deployed under. Developers won't make mistakes when adding new routes.
  2. Native OpenAPI Compatibility: When FastAPI detects a root_path, it automatically and transparently prepends it to the /docs page and openapi.json. You don't need to manually modify the Swagger mounting logic at all.
  3. Universal Compatibility: Whether running via pure uvicorn or as a gunicorn worker, reading the environment variable at the code level guarantees the prefix is applied correctly.

Could you please consider refactoring the backend portion to use the root_path approach based on these suggestions? Looking forward to your next commit! Feel free to ping me if you have any questions.

opencode and others added 12 commits May 8, 2026 00:03
- Pass api_prefix to FastAPI's root_path parameter for reverse proxy support
- Revert all manual route prefixing (/p() helper, include_router prefix=)
- Routes stay at their natural paths (/docs, /query, /health, etc.)
- FastAPI injects root_path into ASGI scope so both /prefix/path and /path work
- Add tests for: root_path configuration, natural path accessibility,
  OpenAPI spec servers URL, WebUI mount with and without api_prefix
- All 13 path prefix tests pass
- add autouse fixture to clear env vars loaded from developer .env
- set minimal ollama defaults so create_app validation passes
- prevent flaky failures due to mismatched local api keys or hosts
…upport

- add _normalize_path helper to sanitize api_prefix and webui_path inputs
- strip trailing slashes and ensure leading slash to prevent Starlette mount errors
- treat empty or "/" as default to avoid misconfiguration
- prepend ASGI root_path in redirects for correct reverse proxy behavior
- update env.example comments to explain build-time VITE prefix requirements
- add comprehensive tests for edge cases like trailing slash and slash-only input
- introduce normalizeApiPrefix and normalizeWebuiPrefix for consistent path handling
- replace inline env var fallbacks in constants.ts with new utilities
- fix vite.config.ts to load env vars via loadEnv instead of import.meta.env
- add comprehensive bun test suite covering edge cases and safety invariants
- expand env.example comments to clarify backend/frontend split for reverse proxy deployments
- add new lightrag_webui/.env.example template with build-time Vite variable documentation
- document VITE_API_PREFIX and VITE_WEBUI_PREFIX in vite-env.d.ts with usage constraints
- expand env.example comments to cover multi-site reverse-proxy deployments
- add nginx configuration example and clarify backend/frontend split
- rewrite lightrag_webui/.env.example with multi-site use case and build instructions
- update vite-env.d.ts inline docs to include multi-site examples and runtime config note
- remove `.env.example` to eliminate duplication with `.env.development`
- add reverse-proxy documentation to `.env.development` and `env.local.sample`
- keep example values commented out in both files for clarity
- add check_webui_build_prefix function to detect baked prefix mismatches
- emit warning with exact rebuild command when prefix disagrees with server config
- add comprehensive tests for match, mismatch, and missing build scenarios
- convert module-level router instances to local variables inside `create_*_routes` factories
- prevent duplicate route accumulation when factories is invoked multiple times in the same process
- remove re-exports from `__init__.py` to avoid exposing stale singleton routers
- add detailed comments explaining the factory pattern and rationale
@danielaskdd danielaskdd merged commit db2cfa5 into HKUDS:main May 8, 2026
@shahrin014
Copy link
Copy Markdown
Author

Sorry I see you have merged it while I am still working on some changes...

At the same time I see you also made some changes.

I'll pull and rebase. Give me till tonight to confirm.

@danielaskdd
Copy link
Copy Markdown
Collaborator

PR #3039 resolves the issue where URL prefix changes no longer require recompilation, enabling seamless Docker container and cloud-native deployments. Additionally, it simplifies prefix configuration by removing the LIGHTRAG_WEBUI_PATH environment variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request tracked Issue is tracked by project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants