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, potentially with a custom lifecycle
  2. defining functions as HTTP endpoints attached to a router with the @router.method decorator
  3. Including routers in other routers, eventually in the app
  4. using uvicorn (or equivalents) to start the app within __main__

streamlit-octostar-utils.api_crafter.fastapi extends point 2. and 3. by:

  • Providing an abstract Route class. Developers can inherit from this class inside which they can define one or more endpoints. This allows functions to be separated into their own classes thus keeping the main file clean
  • Extending the @router.method decorator with the @Route.route decorator, which takes as arguments a Route instance (typically self), a FastAPI router router, plus the same arguments as the FastAPI decorator. This decorator allows dynamic binding of a function as a FastAPI route, where routes inside the same Route can be directed to different FastAPI routers. This binding happens for all functions decorated with the @Route.route decorator inside the define_routes() method, when the include_routes() method is called on the Route instance. This follows a syntax similar to FastAPI's router.include_router()
  • Providing an additional @Route.include() decorator, which simply sets the underlying function as an attribute in the class instance. This effectively allows us to expose instance functions defined inside another function as class attributes

The structure of an endpoint is a class of type Route with a few different methods:

  • define_routes() is native to the Route class, and should be used to define one or more FastAPI routes (usually variants on the same computation) using the @Route.route decorator. Routes defined here will be bound to the associated routers when calling include_routes().
  • __init__() defines the base attributes for the Route. Because of the new @Route.route decorator, the endpoints can refer to self and therefore to any attributes defined in this constructor.

Thanks to this class we can do the following: instantiate an app plus one or more routers, instantiate one 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.