
Security News
GitHub Actions Pricing Whiplash: Self-Hosted Actions Billing Change Postponed
GitHub postponed a new billing model for self-hosted Actions after developer pushback, but moved forward with hosted runner price cuts on January 1.
fastapi-controllers
Advanced tools
A simple solution for organizing your FastAPI endpoints
fastapi-controllers offers a simple solution for organizing your API endpoints by means of a Controller class embracing the concept of class-based views.
pip install fastapi-controllers
import uvicorn
from fastapi import FastAPI, Response, status
from fastapi.websockets import WebSocket
from fastapi_controllers import Controller, get, websocket
class ExampleController(Controller):
@get("/example", response_class=Response)
async def get_example(self) -> Response:
return Response(status_code=status.HTTP_200_OK)
@websocket("/ws")
async def ws_example(websocket: WebSocket) -> None:
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Received: {data}")
if __name__ == "__main__":
app = FastAPI()
app.include_router(ExampleController.create_router())
uvicorn.run(app)
FastAPI's APIRouter is created and populated with API routes by the Controller.create_router method and can be incorporated into the application in the usual way via app.include_router.
The router-related parameters as well as those of HTTP request-specific and websocket decorators are expected to be the same as those used by fastapi.APIRouter, fastapi.APIRouter.<request_method> and fastapi.APIRouter.websocket. Validation of the provided parameters is performed during initialization via the inspect module. This ensures compatibility with the FastAPI framework and prevents the introduction of a new, unnecessary naming convention.
from fastapi_controllers import delete, get, head, options, patch, post, put, trace, websocket
Class variables can be used to set the commonly used APIRouter parameters: prefix, dependencies and tags.
import uvicorn
from fastapi import Depends, FastAPI, Response, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from pydantic import BaseModel
from fastapi_controllers import Controller, get, post
security = HTTPBasic()
async def authorized_user(credentials: HTTPBasicCredentials = Depends(security)) -> None:
...
class ExampleRequest(BaseModel):
name: str
class ExampleResponse(BaseModel):
message: str
class ExampleController(Controller):
prefix = "/example"
tags = ["example"]
dependencies = [Depends(authorized_user)]
@get("", response_class=Response)
async def get_example(self) -> Response:
return Response(status_code=status.HTTP_200_OK)
@post("", response_model=ExampleResponse)
async def post_example(self, data: ExampleRequest) -> ExampleResponse:
return ExampleResponse(message=f"Hello, {data.name}!")
if __name__ == "__main__":
app = FastAPI()
app.include_router(ExampleController.create_router())
uvicorn.run(app)
Additional APIRouter parameters can be provided via the __router_params__ class variable in form of a mapping.
import uvicorn
from fastapi import FastAPI, Response, status
from fastapi_controllers import Controller, get
class ExampleController(Controller):
prefix = "/example"
tags = ["example"]
__router_params__ = {"deprecated": True}
@get("", response_class=Response)
async def get_example(self) -> Response:
return Response(status_code=status.HTTP_200_OK)
if __name__ == "__main__":
app = FastAPI()
app.include_router(ExampleController.create_router())
uvicorn.run(app)
:warning: Important: Beware of assigning values to the same parameter twice (directly on class-level and through
__router_params__). The values stored in__router_params__have precedence and will override your other settings if a name conflict arises. E.g. the followingControllerwould create anAPIRouterwithprefix=/override,tags=["override"]anddependencies=[Depends(override)]
from fastapi import Depends
from fastapi_controllers import Controller
class ExampleController(Controller):
prefix = "/example"
tags = ["example"]
dependencies = [Depends(example)]
__router_params__ = {
"prefix": "/override",
"tags": ["override"],
"dependencies": [Depends(override)],
}
Instance-scoped attributes can be defined in the __init__ method of the Controller and offer an easy way to access common dependencies for all endpoints.
import json
import uvicorn
from fastapi import Depends, FastAPI, Response, status
from fastapi_controllers import Controller, get
class DbSession:
@property
def status(self) -> str:
return "CONNECTED"
async def get_db_session() -> DbSession:
return DbSession()
class ExampleController(Controller):
prefix = "/example"
def __init__(self, session: DbSession = Depends(get_db_session)) -> None:
self.session = session
@get("", response_class=Response)
async def get_status(self) -> Response:
return Response(
content=json.dumps({"status": f"{self.session.status}"}),
status_code=status.HTTP_200_OK,
media_type="application/json",
)
if __name__ == "__main__":
app = FastAPI()
app.include_router(ExampleController.create_router())
uvicorn.run(app)
FAQs
Simple Controller implementation for FastAPI
We found that fastapi-controllers demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
GitHub postponed a new billing model for self-hosted Actions after developer pushback, but moved forward with hosted runner price cuts on January 1.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.