I wrote a simple custom Middleware as below:
class LoggingMiddleware(BaseHTTPMiddleware):
def __init__(self, app):
super().__init__(app)
async def dispatch(self, request, call_next):
user_token = request.headers.get("x-token")
req_id = time_ns()
try:
user_phone_number = decode(user_token, JWT_SECRET_KEY, algorithms=[HASH_ALGORITHM]).get("phone_number")
except:
user_phone_number = ''
req_body = await get_json(request)
reqb = dumps(req_body.decode('utf-8', 'ignore'), ensure_ascii=False)
self.req_logger.info()
response_time = 0
try:
s = time.time()
resp = await call_next(request)
response_time = round(time.time() - s, 2)
except:
self.error_logger.error()
raise CustomException(
details=ErrorResponseSerializer(
)
),
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
)
resp_body = b""
async for item in resp.body_iterator:
resp_body += item
respb = dumps(resp_body.decode('utf-8', 'ignore'), ensure_ascii=False)
if resp.status_code != 200:
self.error_logger.error()
return Response(
content=resp_body,
status_code=resp.status_code,
headers=dict(resp.headers),
media_type=resp.media_type
)
and in one of my endpoints I wrote this functionality:
@router.get("/statistics/contract/count/", response_model=StatisticsCountsResponseSerializer)
def get_contract_count(
province: str = None,
dashboard_status: DashboardContractStatus = None,
status: ContractStatus = None,
csv: int = 0,
context: Context = Depends(get_context)):
repository = PostgresContractRepository(context=context)
result = repository.get_counts(PROVINCES.get(province), dashboard_status, status)
if not csv:
return StatisticsCountsResponseSerializer.parse_obj({"count": result})
else:
filename = f"contract_counts_{int(datetime.datetime.utcnow().timestamp())}.csv"
return StreamingResponse(
# get_csv() yield an string which has csv format: yield "name,fmaily\nemad,emad"
get_csv(),
media_type="text/csv",
headers={"Content-Disposition": f'attachment; filename="{filename}"'}
)
when I send the request to this endpoint I gave this error in postman:
<html>
<head><title>504 Gateway Time-out</title></head>
<body>
<center><h1>504 Gateway Time-out</h1></center>
<hr><center>nginx/1.20.1</center>
</body>
</html>
When I remove my middleware, everything is right and I got the excpected response. Maybe its useful to know that in other endpoints I return FileResponse and with the Middleware everything works fine. Just with StreamingResponse and Middleware I cannot get response.
Edit #1
After reading one of my comments, in this link, I change my code to this one:
async def dispatch(self, request, call_next):
# self.check_authorization(request)
user_token = request.headers.get("x-token")
try:
user_phone_number = decode(user_token, JWT_SECRET_KEY, algorithms=[HASH_ALGORITHM]).get("phone_number")
except:
user_phone_number = ''
details = {
"token": {
"phone_number": user_phone_number
},
"request": {
"id": time_ns(),
"url_path": request.url.path,
"query_params": request.query_params,
"path_params": request.path_params
},
"response": {
"duration": 0.0,
"status_code": 200,
"exception": None
}
}
request_body = await get_json(request)
try:
s = time.time()
response = await call_next(request)
details["response"]["duration"] = round(time.time() - s, 2)
except:
self.error_logger.error(
Logger.message_formatter(
request_id=details.get("request").get("id"),
path=request.url.path,
token_phone_number=user_phone_number,
query_params=request.query_params,
path_params=request.path_params,
body=request_body.decode('utf-8', 'ignore')
)
)
self.error_logger.error(
Logger.message_formatter(
request_id=details.get("request").get("id"),
path=request.url.path,
message=traceback.format_exc(),
status=500
)
)
raise CustomException(
details=ErrorResponseSerializer(
metadata=MessageResponseSerializer(
type=MessageTypeEnum.error,
text=MessageTextResponseSerializer(
text="internal server error",
translate="..."
)
)
),
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
)
response_body = b""
async for item in response.body_iterator:
response_body += item
return Response(
content=response_body,
status_code=response.status_code,
headers=dict(response.headers),
media_type=response.media_type,
background=BackgroundTask(self.log, request_body, response_body, details)
)
But the problem does not solve. I still get time out.