Hi, I working on FastAPI. I would like to get or access the attribute from Response object. As i know It's StreamingResponse type. It's look like async_generator. I've read the document from https://www.starlette.io/responses/#streamingresponse. This instruction look like writing on the Response object. It's don't have a instruction about getting body object from response. Then i trying to find the solution from https://github.com/tiangolo/fastapi/issues/623. but now the link for solution has been expired.
So anyone have idea or example ?
Thank you.
Is this one ?
Is this one ?
What section in article?
I had seen that before, It's no mention on Response Body, just only response header.
@bozzlab Sorry, the docs got reorganized and the link moved. It is fixed in that issue now, but it is also here for reference: https://fastapi.tiangolo.com/advanced/custom-request-and-route/
@bozzlab Sorry, the docs got reorganized and the link moved. It is fixed in that issue now, but it is also here for reference: https://fastapi.tiangolo.com/advanced/custom-request-and-route/
Thank you for the documents, But now i'm working in this style
app.middleware('http')
async def middleware(request: Request, call_next) -> Response:
response = await call_next(request) # response has been StreamingResponse Type
#do something() instead that line to convert Request -> JSONResponse
return response
So, If i would like to get Response Body using this way. Is possible ?
So... did you solve your issue @bozzlab ? If that's the case, you can close the issue.
So... did you solve your issue @bozzlab ? If that's the case, you can close the issue.
Not yet, I'm still finding solution for this.
I ran into a similar situation, for my use case I created a subclass of the response type I needed and added the extra parameter I would have added inside the middleware.
class SnakeCaseResponse(UJSONResponse):
def render(self, content: typing.Any) -> bytes:
content['is_success'] = 'error' not in content
return super().render(convert_to_camel_case(content))
same problem, I am trying to get the body of a request and response in middleware/custom router.
Getting the request body in a middleware can be problematic and in some cases not possible, as the request's body is "consumed".
But to solve those use cases where you are sure your request's body won't be gigantic (or infinite), for example, it's a simple JSON, and you want to access the JSON body in something like a middleware and also in the path operations, you can apply the ideas from this section, let me paste the link again: https://fastapi.tiangolo.com/advanced/custom-request-and-route/#accessing-the-request-body-in-an-exception-handler
Please read the docs there. That should help you solve your use cases.
@tiangolo Would it be possible to attach raw content to the Response object?
class Response:
media_type = None
charset = "utf-8"
def __init__(
self,
content: typing.Any = None,
status_code: int = 200,
headers: dict = None,
media_type: str = None,
background: BackgroundTask = None,
) -> None:
self.body = self.render(content) # <-- self.content = content
self.status_code = status_code
if media_type is not None:
self.media_type = media_type
self.background = background
self.init_headers(headers)
I want to log the content of a JSONResponse as formatted json, but the only way to access it is in a custom APIRoute handler wrapper is after it has been transformed into json bytes.
Now I have to do json.load(response.body) with small perf impact.
Is there a reason why raw content is not exposed or is a bad idea?
I guess I could make my own custom response class...although this might be a bit tricky.
Getting the request body in a middleware can be problematic and in some cases not possible, as the request's body is "consumed".
But to solve those use cases where you are sure your request's body won't be gigantic (or infinite), for example, it's a simple JSON, and you want to access the JSON body in something like a middleware and also in the _path operations_, you can apply the ideas from this section, let me paste the link again: https://fastapi.tiangolo.com/advanced/custom-request-and-route/#accessing-the-request-body-in-an-exception-handler
Please read the docs there. That should help you solve your use cases.
Hi @tiangolo, thanks for your help and for all the efforts in this project!
But I think in this case you get it wrong, @bozzlab is looking for response body, not request body...
@ronanfernandes @tiangolo is has actually pointed in the right direction, maybe not being explicit enough.
There is not reliable way to access response from middleware, but does it actually need to be read in the middleware?
You need to create a CustomAPI route, because the response body in the middleware can be a StreamingResponse or could be gzipped or many other things.
The only safe way to access it is by wrapping the execution of the api route.
This example is at the bottom of the page @tiangolo has linked, and shows you exactly how you can access the response.
import time
from typing import Callable
from fastapi import APIRouter, FastAPI, Request, Response
from fastapi.routing import APIRoute
class TimedRoute(APIRoute):
def get_route_handler(self) -> Callable:
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request) -> Response:
before = time.time()
response: Response = await original_route_handler(request)
duration = time.time() - before
response.headers["X-Response-Time"] = str(duration)
print(f"route duration: {duration}")
print(f"route response: {response}")
print(f"route response headers: {response.headers}")
return response
return custom_route_handler
app = FastAPI()
router = APIRouter(route_class=TimedRoute)
@app.get("/")
async def not_timed():
return {"message": "Not timed"}
@router.get("/timed")
async def timed():
return {"message": "It's the time of my life"}
app.include_router(router)
thank you, it麓s clearer now.
@vjpr you could probably create a sub-class of JSONResponse with your custom implementation, overriding its initialization and storing the data you need in a custom attribute.
Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues.
Most helpful comment
@ronanfernandes @tiangolo is has actually pointed in the right direction, maybe not being explicit enough.
There is not reliable way to access response from middleware, but does it actually need to be read in the middleware?
You need to create a CustomAPI route, because the response body in the middleware can be a StreamingResponse or could be gzipped or many other things.
The only safe way to access it is by wrapping the execution of the api route.
This example is at the bottom of the page @tiangolo has linked, and shows you exactly how you can access the response.