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)