FastAPI Adapter Documentation¶
Overview¶
The FastAPI adapter integrates REROUTE's file-based routing with FastAPI applications, providing seamless OpenAPI documentation and automatic validation.
Features¶
- File-based routing: Automatically discovers and registers routes from
routes/directory - Native OpenAPI support: Built-in Swagger UI and ReDoc (can be disabled)
- Auto-reload: Automatic module detection for uvicorn reload
- Flexible configuration: Override config values at runtime
- CORS support: Built-in CORS middleware
- Type validation: Automatic request/response validation via Pydantic
Basic Setup¶
from fastapi import FastAPI
from reroute.adapters import FastAPIAdapter
from config import AppConfig
# Create FastAPI app
app = FastAPI()
# Initialize REROUTE adapter
adapter = FastAPIAdapter(
fastapi_app=app,
app_dir="./app",
config=AppConfig
)
# Register all file-based routes
adapter.register_routes()
# Add manual routes (optional)
@app.get("/")
def root():
"""Welcome endpoint"""
return {
"message": "Welcome to My API",
"docs": "/docs"
}
# Run server
if __name__ == "__main__":
adapter.run_server()
Configuration¶
OpenAPI Configuration¶
from reroute import Config
class AppConfig(Config):
# Server Configuration
HOST = "0.0.0.0"
PORT = 7376
AUTO_RELOAD = True
# OpenAPI/Swagger Documentation
class OpenAPI:
ENABLE = True # Enable/disable all documentation
# Documentation Endpoints
DOCS_PATH = "/docs" # Swagger UI (set to None to disable)
REDOC_PATH = "/redoc" # ReDoc UI (set to None to disable)
JSON_PATH = "/openapi.json" # OpenAPI spec endpoint
# API Metadata
TITLE = "My API"
VERSION = "1.0.0"
DESCRIPTION = "My API built with REROUTE"
Documentation UIs¶
When OpenAPI is enabled, the following endpoints are available:
- Swagger UI:
http://localhost:7376/docs - ReDoc UI:
http://localhost:7376/redoc - OpenAPI Spec:
http://localhost:7376/openapi.json
Disabling Documentation¶
To disable specific UIs, set their paths to None:
class OpenAPI:
ENABLE = True
DOCS_PATH = "/docs" # Swagger enabled
REDOC_PATH = None # ReDoc disabled
JSON_PATH = None # OpenAPI JSON disabled
Note: When you set a path to None, the route is completely removed from FastAPI - you'll get a 404 when accessing it.
Running the Server¶
Basic Usage¶
Override Parameters¶
# Override port
adapter.run_server(port=8080)
# Override multiple parameters
adapter.run_server(
port=8080,
reload=False,
workers=4
)
# Custom log level
adapter.run_server(
log_level="debug",
access_log=True
)
Available Parameters¶
Common uvicorn parameters:
host(str): Host to bind (default: from config.HOST)port(int): Port to bind (default: from config.PORT)reload(bool): Enable auto-reload (default: from config.AUTO_RELOAD)workers(int): Number of worker processeslog_level(str): Logging level ("critical", "error", "warning", "info", "debug", "trace")access_log(bool): Enable access loguse_colors(bool): Enable colored loggingproxy_headers(bool): Enable X-Forwarded-Proto, X-Forwarded-For headersforwarded_allow_ips(str): Comma-separated list of IPs to trust with proxy headers
Auto-Reload¶
When AUTO_RELOAD = True or reload=True is passed, the adapter automatically detects the import string:
Output:
Request Validation¶
FastAPI automatically validates requests using Pydantic models:
from fastapi import Query
from pydantic import BaseModel
class User(BaseModel):
name: str
email: str
age: int
@app.post("/users")
def create_user(user: User):
"""Create a new user"""
return {
"id": 1,
"name": user.name,
"email": user.email
}
@app.get("/users")
def list_users(
page: int = Query(default=1, description="Page number"),
limit: int = Query(default=10, description="Items per page")
):
"""List users with pagination"""
return {
"page": page,
"limit": limit,
"users": []
}
CORS Configuration¶
class AppConfig(Config):
ENABLE_CORS = True
CORS_ALLOW_ORIGINS = ["*"] # or ["http://localhost:3000"]
CORS_ALLOW_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
CORS_ALLOW_HEADERS = ["*"]
CORS_ALLOW_CREDENTIALS = False
CORS is implemented via FastAPI's CORSMiddleware.
File-Based Routes¶
Create routes in app/routes/ directory:
Example: app/routes/users/page.py
from reroute import RouteBase
from pydantic import BaseModel
class UserCreate(BaseModel):
name: str
email: str
class UserRoutes(RouteBase):
tag = "Users" # OpenAPI tag
def get(self, user_id: int):
"""Get user by ID"""
return {"id": user_id, "name": "John"}
def post(self, user: UserCreate):
"""Create new user"""
return {
"id": 1,
"name": user.name,
"email": user.email
}
Error Handling¶
from fastapi import FastAPI, HTTPException
from reroute.adapters import FastAPIAdapter
app = FastAPI()
adapter = FastAPIAdapter(app)
@app.exception_handler(404)
async def not_found_handler(request, exc):
return {"error": "Not found"}
@app.exception_handler(500)
async def server_error_handler(request, exc):
return {"error": "Internal server error"}
# Custom exception
class UserNotFoundError(Exception):
pass
@app.exception_handler(UserNotFoundError)
async def user_not_found_handler(request, exc):
return {"error": "User not found"}
Async Support¶
FastAPI fully supports async/await:
from reroute import RouteBase
class UserRoutes(RouteBase):
async def get(self, user_id: int):
"""Async get user"""
# Simulate async DB call
await asyncio.sleep(0.1)
return {"id": user_id, "name": "John"}
async def post(self, user: UserCreate):
"""Async create user"""
await save_to_db(user)
return {"id": 1, "created": True}
Background Tasks¶
from fastapi import BackgroundTasks
@app.post("/send-email")
def send_email(email: str, background_tasks: BackgroundTasks):
"""Send email in background"""
background_tasks.add_task(send_email_task, email)
return {"message": "Email will be sent"}
def send_email_task(email: str):
# Actual email sending logic
pass
Dependencies¶
Use FastAPI's dependency injection:
from fastapi import Depends
def get_current_user(token: str = Header()):
# Verify token and return user
return {"id": 1, "name": "John"}
@app.get("/me")
def get_me(user = Depends(get_current_user)):
"""Get current user"""
return user
Best Practices¶
-
Use config for defaults, kwargs for overrides: Keep standard settings in config, use
run_server()kwargs for temporary changes -
Disable unused docs: Set
REDOC_PATH = Noneif you only use Swagger -
Use async when possible: Async routes improve performance for I/O-bound operations
-
Tag your routes: Use
tagattribute in RouteBase for organized documentation -
Enable reload in development: Set
AUTO_RELOAD = Truein DevConfig -
Use dependency injection: Leverage FastAPI's Depends for authentication, database connections, etc.
Troubleshooting¶
Auto-reload not working¶
- Make sure
AUTO_RELOAD = Trueor passreload=True - Verify the adapter can detect the module (check for "[INFO] Auto-reload enabled" message)
- If it shows a warning, run directly:
uvicorn main:app --reload
Documentation not showing¶
- Check if
OpenAPI.ENABLE = Truein config - Verify paths are not set to
None - Access the correct URLs:
/docsor/redoc
Routes not registering¶
- Verify
routes/directory exists - Check file is named
page.py - Ensure class inherits from
RouteBase - Check for any import errors in your route files
CORS errors¶
- Set
ENABLE_CORS = Truein config - Add your frontend origin to
CORS_ALLOW_ORIGINS - Verify
CORS_ALLOW_CREDENTIALSsetting
Deployment¶
Production Settings¶
class ProdConfig(Config):
DEBUG = False
AUTO_RELOAD = False
LOG_LEVEL = "WARNING"
class OpenAPI:
ENABLE = False # Disable docs in production
# Run with multiple workers
adapter.run_server(workers=4, log_level="warning")
Docker¶
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Uvicorn Direct¶
If you prefer running uvicorn directly: