Backend/Python

Traefik err - Unsolicited response received on idle HTTP channel starting with ""(+ FastAPI)

chani 2023. 4. 5. 16:10

 

 

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에서 검출되지도 않았고, 이후로 컨테이너가 죽는 현상도 발생하지는 않아서, 아마도 이 문제가 맞을 것이라고 생각하고 있지만..

그래도 계속 지켜보고 탐색할 예정이다.

 

 

 

 

참조

https://www.binaryflavor.com/fastapi-yi-204/

https://github.com/tiangolo/fastapi/issues/717