FastAPI와 Traefik을 Docker container로 사용하던 도중 발생한 이슈로
Traefik을 LB로 사용하던 도중 계속해서 죽는 이슈가 발생하였고(컨테이너가 내려가지 않아서 docker engine을 내려야 했음)
추후 Traefik의 에러 로그를 찍어보니
transport.go:2196: Unsolicited response received on idle HTTP channel starting with "{\"status\":\"success\",\"message\":\"삭제 성공\"}"; err=<nil>
transport.go:2196: Unsolicited response received on idle HTTP channel starting with "{\"status\":\"success\",\"message\":\"삭제 성공\"}"; err=<nil>
transport.go:2196: Unsolicited response received on idle HTTP channel starting with "{\"status\":\"success\",\"message\":\"삭제 성공\"}"; err=<nil>
transport.go:2196: Unsolicited response received on idle HTTP channel starting with "{\"status\":\"success\",\"message\":\"삭제 성공\"}"; err=<nil>
transport.go:2196: Unsolicited response received on idle HTTP channel starting with "{\"status\":\"success\",\"message\":\"삭제 성공\"}"; err=<nil>
라는 오류가 잔뜩 찍혀 있었다.
계속해서 공통점을 찾던 도중 에러를 뿜어 낸 녀석들이 죄다 status code가 204인걸 찾아냈고, 이 문제일 것이라 생각하여 탐색했다.
기존 코드는
#예시코드
@router.delete('/test/{id}', status_code=204, tags=['test'])
async def text_delete(data: data):
if status:
return {'status': "success", 'message': '삭제 성공'}
else:
raise HTTPException(status_code=404, detail=object.message)
삭제 성공시 204 리턴 / 실패시 404
204와 함께 dict을 리턴하고 있었는데
https://velog.io/@server30sopt/204-NOCONTENT%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%84%EC%8B%9C%EB%82%98%EC%9A%94 을 참조하면 204 No Content는 Body가 없다...!(주고 있는데 없다..!)
즉, Body가 없이 리턴해야 하는데 리턴값을 주고 있었고
위의 코드를 수정해도
#예시코드
@router.delete('/test/{id}', status_code=204, tags=['test'])
async def text_delete(data: data):
if not status:
raise HTTPException(status_code=404, detail=object.message)
return 부분을 날렸다..
transport.go:2196: Unsolicited response received on idle HTTP channel starting with "null"; err=<nil>
아예 null 값으로 보내버린다....
(사수분께 물어보니 204의 리턴의 Body를 받아줄 수도, 무시할 수도 있지만 에러를 뿜어낼 수도 있다고 한다...)
여튼 FastAPI에서 204를 제대로 Body없이 보내려면
#예시코드
@router.delete('/test/{id}', status_code=204, tags=['test'])
async def text_delete(data: data):
if status:
return Response(status_code=204)
else:
raise HTTPException(status_code=404, detail=object.message)
로 Response를 명시적으로 리턴하면 해결되었다..
기존과 같던 에러가 Traefik에서 검출되지도 않았고, 이후로 컨테이너가 죽는 현상도 발생하지는 않아서, 아마도 이 문제가 맞을 것이라고 생각하고 있지만..
그래도 계속 지켜보고 탐색할 예정이다.
참조