Utilities for FastAPI
The Route Class
A server built with FastAPI typically defines its functionality by:
- Defining an
appinstance: This may include a custom lifecycle. - Defining functions as HTTP endpoints: These are attached to a router using the
@router.methoddecorator. - Including routers in other routers: Eventually, these are included in the app.
- Starting the app: Use
uvicorn(or equivalents) to start the app within__main__.
streamlit-octostar-utils.api_crafter.fastapi enhances points 2 and 3 by:
- Abstract
RouteClass: Developers can inherit from this class to define one or more endpoints. This separation keeps the main file clean. - Extended Decorator: The
@Route.routedecorator extends the@router.methoddecorator. It takes aRouteinstance (typicallyself), a FastAPI routerrouter, and the same arguments as the FastAPI decorator. This allows dynamic binding of functions as FastAPI routes, directing routes inside the sameRouteto different FastAPI routers. Binding occurs for all functions decorated with@Route.routeinside thedefine_routes()method wheninclude_routes()is called on theRouteinstance, following a syntax similar to FastAPI'srouter.include_router(). - Additional
@Route.include()Decorator: This sets the underlying function as an attribute in the class instance, allowing instance functions defined inside another function to be exposed as class attributes.
Structure of an Endpoint
An endpoint is structured as a class of type Route with several methods:
define_routes(): Native to the Route class, this method defines one or more FastAPI routes (usually variants on the same computation) using the@Route.routedecorator. Routes defined here bind to associated routers wheninclude_routes()is called.__init__(): This method defines the base attributes for theRoute. The new@Route.routedecorator allows endpoints to refer toselfand any attributes defined in this constructor.
Implementation
With this class, you can:
- Instantiate an app and one or more routers.
- Instantiate a
Route. - Call
include_routes()on the route instance to bind its endpoints to the router(s). - Call
include_router()on the app to include the routers into the whole app.