-
Notifications
You must be signed in to change notification settings - Fork 1
LitePolis Package URI routing behavior
This guide explains how API URLs are structured and managed in LitePolis, ensuring that different router packages can coexist without conflicts.
LitePolis follows a standardized URL structure that ensures unique endpoints across all router packages:
/api/{router-prefix}/{endpoint-path}
Where:
-
/api/is the base path for all API endpoints -
{router-prefix}is specific to each router package -
{endpoint-path}is defined by the router package for its specific functionality
Each router package in LitePolis is isolated from others through several mechanisms:
-
Prefix-Based Routing: Every router package defines its own unique
prefixthat becomes part of the URL path - FastAPI Sub-Router Architecture: Each router is a FastAPI Router object mounted at its own prefix
When examining the core.py code, we can see how routers are registered:
for import_name in routers:
m = importlib.import_module(import_name)
try:
app.include_router(
m.router,
prefix=f'/api/{m.prefix}',
dependencies=m.dependencies
)
except Exception as e:
print(f"Error importing router {import_name}: {e}")This ensures that:
- Each router is mounted at its own unique prefix path
- Router dependencies are preserved
- Error handling prevents a failing router from affecting others
Here are examples of how different router packages would have their endpoints mounted:
| Package Name | Import Name | Prefix | Full URL Path |
|---|---|---|---|
| litepolis-router-auth | litepolis_router_auth | auth | /api/auth/login |
| litepolis-router-users | litepolis_router_users | users | /api/users/profile |
| litepolis-router-docs | litepolis_router_docs | docs | /api/docs/search |
| litepolis-router-payment | litepolis_router_payment | payment | /api/payment/checkout |
| litepolis-router-default | litepolis_router_default | v3 | /api/v3/status |
When developing a new router package, you must define your prefix:
# In litepolis_router_example/__init__.py
from fastapi import APIRouter, Depends
# Create the router
router = APIRouter()
# Define the prefix for this router package
prefix = "example" # This will mount at /api/example/...
# Define any FastAPI dependencies for all routes in this router if it is not included in the package
dependencies = []
# Add routes to your router
@router.get("/hello") # Will be accessible at /api/example/hello
def hello_world():
return {"message": "Hello from example router!"}To avoid conflicts, some prefixes are reserved by the LitePolis system:
-
v1,v2,v3, etc.: Reserved for core API versions -
docs: Reserved for API documentation (Swagger/ReDoc) -
openapi.json: Reserved for OpenAPI schema
UI packages have separate routing that doesn't interfere with API routes:
for import_name in user_interfaces:
m = importlib.import_module(import_name)
try:
app.include_router(m.prefix, m.files, name=m.name)
except Exception as e:
print(f"Error importing UI {import_name}: {e}")
This allows UI components to coexist with API routes without path conflicts.
To verify your router's URL paths:
-
Run LitePolis locally:
litepolis deploy local -
Visit the auto-generated documentation:
http://localhost:8000/docs -
All available endpoints will be displayed with their full paths.
- Choose Descriptive Prefixes: Your prefix should clearly indicate the domain or functionality
-
Use REST Conventions: Follow REST principles in your endpoint design
- GET /api/users/ (list)
- POST /api/users/ (create)
- GET /api/users/{id} (retrieve)
- PUT /api/users/{id} (update)
- DELETE /api/users/{id} (delete)
-
Consistent Casing: Use kebab-case for URL paths (e.g.,
/api/user-profiles/) -
Versioning Strategy: Consider including versions in your router for future compatibility:
prefix = "users/v1" # Will mount at /api/users/v1/...
If you encounter URL conflicts:
- Check for Duplicate Prefixes: Ensure no two router packages use the same prefix
-
Inspect Deployed Routers: Use
litepolis deploy list-depsto see all installed router packages - Review FastAPI Logs: Error messages will indicate if a route couldn't be registered
- Check for Reserved Prefixes: Ensure you're not using a reserved prefix