🛡️ Middlewares

Middleware functions are used to intercept requests before they reach the main logic of the application. In Lila, core middlewares are defined in the core/middleware.py file. Middlewares can be used for tasks such as authentication, logging, security, and error handling.

Lila uses a unified Middleware manager that provides both class-based HTTP middlewares and route decorators.

✨ Default Route Middlewares

Lila includes several built-in middlewares that can be used as decorators on your routes:

Example usage in routes

from lila.core.middleware import login_required, session_active, validate_token

# Require authentication for this route
@router.get('/dashboard')
@login_required
async def dashboard(request: Request):
    return render(request=request, template='dashboard')

# Redirect authenticated users away from login page
@router.get('/login')
@session_active
async def login_page(request: Request):
    return render(request=request, template='login')

# Validate JWT for API routes
@router.get('/api/data')
@validate_token
async def api_data(request: Request):
    return JSONResponse({"data": "secure"})
                    

🛠️ Creating Custom Middlewares

You can easily create your own route middlewares using the create_decorator helper. This tool automatically handles the boilerplate of Python decorators.

core/middleware.py (Custom Middleware)

from core.middleware import create_decorator

@create_decorator
async def check_admin(request: Request, role="admin"):
    # If the logic returns a response, it breaks the chain and returns it
    # If it returns True or None, it continues to the route
    user = request.state.user
    if user.get("role") != role:
        return JSONResponse({"error": "Unauthorized"}, status_code=403)
    return True

# Usage in routes:
# @check_admin -> uses default role="admin"
# @check_admin(role="superadmin") -> uses custom role
                    

🔒 Global Security Middlewares

Lila includes a set of global HTTP middlewares for application-wide protection. These are configured in main.py using the Middleware class.

main.py configuration

from core.middleware import (
    Middleware,
    LoggingMiddleware, 
    SecurityHeadersMiddleware,
    SecurityShieldMiddleware,
    RateLimitMiddleware,
    ErrorHandlerMiddleware,
)

middlewares = [
    Middleware(LoggingMiddleware),
    Middleware(SecurityHeadersMiddleware),
    Middleware(SecurityShieldMiddleware),
    Middleware(RateLimitMiddleware),
    Middleware(ErrorHandlerMiddleware)
]

app = App(..., middleware=middlewares)