How can I have a FastAPI dependency fill in a path parameter?

I am using FastAPI and I want having two routes that reference the same function. I need the value in one of the cases to come from the path operation, while in the other case, I need it to be generated as a dependency.

Below is what I thought would work, but the /inbound case generates a 422 Unprocessable entity error.

def middleware():
    return {"wako_id": "123"}

def test(request: Request, wako_id: str):
    return wako_id

authorized_router.add_api_route(
  "/inbound",
  test,
  dependencies=[Depends(middleware)],
  methods=["GET"]
)

authorized_router.add_api_route(
    "/outbound/{wako_id}",
    test,
    methods=["GET"]
)

You could have the wako_id parameter declared as Optional in the dependecy function (see this and this for more details and examples on optional parameters in FastAPI), then check the raw url path of the request, and if it is the /outbound one, return the wako_id value specified by the user, else if the /inbound route was called return your custom wako_id.

Note that you could also have an else statement and return JSONResponse(content="wako_id is missing", status_code=400) (see this answer for more details on how to return JSON from FastAPI), in case the /outbound route was called without passing the wako_id parameter. However, in your case, you don’t have to do this, as the wako_id is declared as path parameter, and path parameters are always required in FastAPI (you can’t have optional path parameters—you may find helpful posts here, here and here). Hence, if the user sent a request to, for instance, http://127.0.0.1:8000/outbound (without including the wako_id path parameter, e.g., /outbound/some_str_id_here), FastAPI would automatically return a {"detail":"Not Found"} error response.

Finally, I would suggest having a look at this answer, this answer and this answer, as well as this answer, this answer and this answer, in order to better understand how to use Dependencies in FastAPI, as well as how to pass an object or a value from a dependency function to an endpoint, in case you used a global dependency for the entire router or a specific route, using the dependencies argument (similar to the example you provided). Otherwise, you could use the Depends keyword on the parameter in your endpoint, and return the object/value, as shown in the example below.

Example

from fastapi import FastAPI, Request, APIRouter, Depends
from typing import Optional

app = FastAPI()
router = APIRouter()


def get_wako_id(request: Request, wako_id: Optional[str] = None):
    path = request.scope['root_path'] + request.scope['route'].path
    if wako_id and path == '/outbound/{wako_id}':
        return wako_id
    elif path == '/inbound':
        return '123'


def endpoint(wako_id: str = Depends(get_wako_id)):
    return wako_id


router.add_api_route("/inbound", endpoint, methods=["GET"])
router.add_api_route("/outbound/{wako_id}", endpoint, methods=["GET"])
app.include_router(router)

Leave a Comment