사이드프로젝트

[ 기록의 정원 ] Error:Field validation for *** failed on the 'required'

코줍 2024. 6. 12. 14:09

문제 상황

1. 요청 필수필드값을 모두 채웠는데, 에러가 발생한다...

 

축의금 기록을 테스트 하는데, 버튼이 눌린 뒤 반응이 없었다.( 아직 FE분이 에러 토스트 메세지 기능을 붙이기 전이였음.. )

뭐가 문제인가 싶어서 네트워크 탭을 열어보니까 400에러와 함께 아래와 같은 response가 내려왔다.

{ 
    "detail": "Key: 'CreateExpense.IsInvited' Error:Field validation for 'IsInvited' failed on the 'required' tag
    \nKey: 'CreateExpense.Name' Error:Field validation for 'Name' failed on the 'required' tag
    \nKey: 'CreateExpense.EventDate' Error:Field validation for 'EventDate' failed on the 'required' tag"
}

 

payload에 필요한 필드값들을 모두 채워서 요청했음에도 불구하고 위와 같은 에러가 발생한거다.

 

 

2. 초대 서버에 직접 요청하면 정상처리 되는데, 게이트웨이 서버 도메인으로 요청하면 에러가 발생한다.

 

payload를 똑같이해서 요청을 보내도 초대서버 도메인으로 직접 요청했을 땐 문제가 없는데,

게이트웨이 서버 도메인으로 요청했다 하면 에러가 발생했다.

 

- 초대서버 요청 curl

curl --location 'http://175.45.192.38:80/invitation/expense' \
--header 'user_id: d2c7ad7d-f29d-4f24-adb8-4e4650641588' \
--header 'Content-Type: application/json' \
--data '{
    "is_invited": "invited",
    "name": "췰린",
    "event_date": "202406010000",
    "expense": 100000,
    "is_attended": 1
}'

// response 
{
    "event_id": "af45f14f-558c-4325-ba6d-0ac5444d2d61",
    "user_id": "d2c7ad7d-f29d-4f24-adb8-4e4650641588",
    "is_invited": 1,
    "event_date": "2024-06-01T00:00:00Z",
    "name": "가나다",
    "relation": "",
    "amount": 100000,
    "is_attended": 1
}

- 게이트웨이 서버 요청 curl

curl --location 'http://tikitakaapi.site:8000/invitation/expense' \
--header 'access-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMmM3YWQ3ZC1mMjlkLTRmMjQtYWRiOC00ZTQ2NTA2NDE1ODgiLCJleHAiOjE3MTY0Nzc0NTB9.DieTxTUQD4dx_Y9c8bSD1kNOt5hYlB5sGv1zEDbJWGA' \
--header 'Content-Type: application/json' \
--data '{
    "is_invited": "invited",
    "name": "췰린",
    "event_date": "202405230000",
    "expense": 10000,
    "relation": "친구",
    "is_attended": 1
}'

// response
{
    "detail": "Key: 'CreateExpense.IsInvited' Error:Field validation for 'IsInvited' failed on the 'required' tag\nKey: 'CreateExpense.Name' Error:Field validation for 'Name' failed on the 'required' tag\nKey: 'CreateExpense.EventDate' Error:Field validation for 'EventDate' failed on the 'required' tag\nKey: 'CreateExpense.Expense' Error:Field validation for 'Expense' failed on the 'required' tag"
}

 

문제 원인

에러메세지를 파악해보면, body값으로 들어온 데이터들을 제대로 파싱할 수 없기 때문에 발생하는 문제이다.

 

 

위 요청 시나리오를 도식화 해보니 어디서 문제가 발생한 건지 알 수 있었다.

 

1. 클라에서 게이트웨이 서버에 요청을 할 때, accessToken값을 header에 넣어 보낸다.

2. 게이트웨이 서버에서 클라에서 받은 accessToken의 유효성 검증을 하고, user_id값 ( 회원 id )을 추출한다.

3. 추출한 user_id값을 라우팅할 프로토콜에 header를 커스텀하여 보낸다.

 

문제가 되는 과정은 3번!

 

게이트웨이 서버 자체에서 header값이 커스텀되기 때문에

클라이언트에서 처음 요청할 때 보냈던 header값과는 다르게 되는 것이다.

 

즉, 클라에서 Content-Type을 명시해주더라도 게이트웨이 서버에서는 Content-Type에 대한 정보가 유실되어 초대 서버로 하여금 데이터 파싱이 제대로 이루어지지 않았던 것!

 

문제 해결

게이트웨이 서버에서 다른 프로토콜로 body값을 보낼 때, 

Content-Type에 application/json을 명시하여 요청을 보냄으로서 해당 문제가 해결되었다.

 

async with httpx.AsyncClient() as client:
    url = self.get_url(service, path)
    headers = self.header if not user_id else { **self.header, "user_id" : str(user_id), "content-type" : "application/json"} 
    response = await client.post(url, content=await request.body(), headers=headers)

    if response.status_code != 200:
        raise HTTPException(status_code=response.status_code, detail=json.loads(response.content).get("detail"))

    return json.loads(response.content)