Dependency Injection
Dependency Injection (DI) lets you declare reusable components that are automatically resolved and injected into your route handlers. JustAPI’s DI system mirrors FastAPI’s, making migration seamless.
Basic Dependency
Section titled “Basic Dependency”A dependency is any callable that returns a value:
from justapi import JustAPIApp, Depends
app = JustAPIApp()
def common_params(q: str | None = None, skip: int = 0, limit: int = 100): return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")def list_items(request, params: dict = Depends(common_params)): return {"endpoint": "items", **params}
@app.get("/users/")def list_users(request, params: dict = Depends(common_params)): return {"endpoint": "users", **params}curl "http://127.0.0.1:8000/items/?skip=10&limit=5"# Output: {"endpoint":"items","q":null,"skip":10,"limit":5}Authentication Dependency
Section titled “Authentication Dependency”Dependencies can raise HTTPException to reject requests:
from justapi import JustAPIApp, Depends, HTTPException, Header
app = JustAPIApp()
def verify_token(authorization: str = Header(...)): if not authorization.startswith("Bearer "): raise HTTPException(status_code=401, detail="Invalid authorization header") token = authorization.removeprefix("Bearer ") if token != "secret-token": raise HTTPException(status_code=401, detail="Invalid token") return {"user_id": 42, "role": "admin"}
@app.get("/protected")def protected_route(request, user: dict = Depends(verify_token)): return {"message": "Access granted", "user": user}curl http://127.0.0.1:8000/protected# Output: {"detail":"Invalid authorization header"}
curl http://127.0.0.1:8000/protected \ -H "Authorization: Bearer secret-token"# Output: {"message":"Access granted","user":{"user_id":42,"role":"admin"}}Database Session Dependency
Section titled “Database Session Dependency”def get_db(request): db = app.db try: yield db finally: pass # Connection pooling handles cleanup
@app.get("/users")def list_users(request, db=Depends(get_db)): return db.query("SELECT * FROM users")Class-Based Dependencies
Section titled “Class-Based Dependencies”class Pagination: def __init__(self, skip: int = 0, limit: int = 100): self.skip = skip self.limit = limit
@app.get("/items/")def list_items(request, pagination: Pagination = Depends(Pagination)): return {"skip": pagination.skip, "limit": pagination.limit}Dependency Scope & Caching
Section titled “Dependency Scope & Caching”By default, dependencies are called once per request and the result is cached. All route handlers and nested dependencies share the same instance:
def get_db(request): print("Creating DB session") # Called once per request return {"connection": "db-1"}
def get_user(request, db=Depends(get_db)): return {"user": "alice", "db": db}
@app.get("/profile")def profile(request, user=Depends(get_user), db=Depends(get_db)): return {"user": user, "db_again": db}In this example, get_db is called once and its result is reused by get_user and profile.
Dependency with Path(), Query(), Header()
Section titled “Dependency with Path(), Query(), Header()”from justapi import Path, Query, Header
def pagination( skip: int = Query(0, description="Number of items to skip"), limit: int = Query(10, description="Max items per page"),): return {"skip": skip, "limit": limit}
def auth( user_id: int = Path(..., description="User ID"), authorization: str = Header(..., description="Bearer token"),): if authorization != "Bearer secret": raise HTTPException(401) return {"user_id": user_id}
@app.get("/users/{user_id}/items/")def list_items( request, auth_data: dict = Depends(auth), pagination_data: dict = Depends(pagination),): return {**auth_data, **pagination_data}Nested Dependencies
Section titled “Nested Dependencies”Dependencies can depend on other dependencies:
def get_config(request): return {"db_url": "postgres://localhost/mydb"}
def get_db(request, config: dict = Depends(get_config)): return {"connection": f"Connected to {config['db_url']}"}
@app.get("/status")def status(request, db: dict = Depends(get_db)): return {"db_status": db["connection"]}How It Works Internally
Section titled “How It Works Internally”- JustAPI inspects function signatures at registration time
- Parameters with
Depends()are resolved before the handler runs - Dependencies execute in order (innermost first)
- Results are cached to avoid redundant calls
HTTPExceptionraised in a dependency short-circuits the request
Next Steps
Section titled “Next Steps”- Middleware — Request/response interception
- Error Handling — Custom exception handlers
- Database Integration — Real database dependencies