I have a GET
method with requested parameter in path:
@router.get('/users/{user_id}')
async def get_user_from_string(user_id: str):
return User(user_id)
Is it possible to get base url raw path (ie, '/users/{user_id}'
) from the request?
I have tried to use the following way:
path = [route for route in request.scope['router'].routes if
route.endpoint == request.scope['endpoint']][0].path
But it doesn't work and I get:
AttributeError: 'Mount' object has no attribute 'endpoint'
As per FastAPI documentation :
As FastAPI is actually Starlette underneath, with a layer of several tools on top, you can use Starlette's
Request
object directly when you need to.
Thus, you can use Request
object to get the URL path. For instance:
from fastapi import FastAPI, Request app = FastAPI() @app.get('/users/{user_id}') async def get_user(user_id: str, request: Request): print(request.url.path) return "something"
The above will print, for example, /users/1
(if user_id
passed is 1
).
If, however, what you need is the actual path of the endpoint, ie, /users/{user_id}
, then you could use the below:
@app.get("/users/{user_id}") async def get_user(user_id: str, request: Request): p = [route.path for route in app.routes if route.name == request.scope['endpoint'].__name__] print(p[0]) return "something"
If APIRouter is used instead, you can use the below:
for route in request.scope['router'].routes
or,, you could get the app
instance using the Request
object (as described here and here )
for route in request.app.routes
Note: You could always get the above path by simply stroring it in a variable, since you already know the route's path beforehand.
I'm working on implementing this for OpenTelemetry and the way to get the original route with the data that's available is as follows:
def get_route_from_request(req):
root_path = req.scope.get("root_path", "")
route = scope.get("route")
if not route:
return None
path_format = getattr(route, "path_format", None)
if path_format:
return f"{route_path}{path_format}"
return None
Note that the accepted answer is not returning what was asked, as it returns the path as received by the server.
None of the other answers deal with mounted apps.
And finally, answers checking the name of the endpoint are also wrong as the same function could be used in different endpoints.
Having found both the answers to not work I'll share what I use. It's not great as if there's shared values in path params it will not work
path = request.url.path for key, val in request.path_params.items(): path = path.replace(val, F'{{{key}}}')
you can use APIRouter object attribute from Request to get real path
example:
raw_path = request.scope['route'].path #'/user/{id}'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.