Skip to main content

Utilities for FastAPI

The Route Class

A server built with FastAPI typically defines its functionality by:

  1. Defining an app instance: This may include a custom lifecycle.
  2. Defining functions as HTTP endpoints: These are attached to a router using the @router.method decorator.
  3. Including routers in other routers: Eventually, these are included in the app.
  4. 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 Route Class: Developers can inherit from this class to define one or more endpoints. This separation keeps the main file clean.
  • Extended Decorator: The @Route.route decorator extends the @router.method decorator. It takes a Route instance (typically self), a FastAPI router router, and the same arguments as the FastAPI decorator. This allows dynamic binding of functions as FastAPI routes, directing routes inside the same Route to different FastAPI routers. Binding occurs for all functions decorated with @Route.route inside the define_routes() method when include_routes() is called on the Route instance, following a syntax similar to FastAPI's router.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.route decorator. Routes defined here bind to associated routers when include_routes() is called.
  • __init__(): This method defines the base attributes for the Route. The new @Route.route decorator allows endpoints to refer to self and any attributes defined in this constructor.

Implementation

With this class, you can:

  1. Instantiate an app and one or more routers.
  2. Instantiate a Route.
  3. Call include_routes() on the route instance to bind its endpoints to the router(s).
  4. Call include_router() on the app to include the routers into the whole app.