RestTemplate를 통해 타 API를 호출해야하는데, 이 과정에서 401 에러가 발생할 경우 추가설정이 없는 한 다음과 같이 리턴이 온다.
org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 : [no body]
...
문제는 401 에러안에 no Body 로 아무런 데이터가 없이 오는데, 내 경우 저 안에 로그인이 실패한 이유가 담겨서 와야한다. 실제로 통신을 하고나면 다음과 같은 통신이 일어난다.
[TestUserClient#userLogin] ---> POST http://localhost:9021/test/user/login HTTP/1.1
[TestUserClient#userLogin] Authorization: Basic aaaaaa==
[TestUserClient#userLogin] Content-Length: 56
[TestUserClient#userLogin] Content-Type: application/json
[TestUserClient#userLogin]
[TestUserClient#userLogin] {"email":"test@naver.com","password":"test123"}
[TestUserClient#userLogin] ---> END HTTP (56-byte body)
[TestUserClient#userLogin] <--- HTTP/1.1 500 (299ms)
[TestUserClient#userLogin] cache-control: no-cache, no-store, max-age=0, must-revalidate
[TestUserClient#userLogin] connection: close
[TestUserClient#userLogin] content-type: application/json
[TestUserClient#userLogin] date: Tue, 03 Aug 2021 21:53:06 GMT
[TestUserClient#userLogin] expires: 0
[TestUserClient#userLogin] pragma: no-cache
[TestUserClient#userLogin] transfer-encoding: chunked
[TestUserClient#userLogin] x-content-type-options: nosniff
[TestUserClient#userLogin] x-frame-options: DENY
[TestUserClient#userLogin] x-xss-protection: 1; mode=block
[TestUserClient#userLogin]
[TestUserClient#userLogin] {"errorCode": "E10007", "message":"비밀번호를 확인해 주세요."}
[TestUserClient#userLogin] <--- END HTTP (65-byte body)
로그를 보면 message 에 비밀번호를 확인해주세요 라고 리턴을 보내는데도 불구하고 RestTemplate 사용 시 401 에러가 발생하면 아무 메세지를 받지 못하는 것이다. 때문에 왜 로그인에 실패했는지에 대한 안내문구를 전달할 수 없었다.
그래서 이부분을 찾아보니 우선 HttpComponentsClientHttpRequestFactory 를 구현하여 restTemplate 에 설정하면 된다. 그러면 다음처럼 에러메세지에 보이게 된다.
설정하는 방법은 다음과 같다
...
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
...
설정 전과 후를 비교하면 다음과 같다.
설정을 안했을 때
설정한 후
통신 중 성공이 아닌 에러가 발생하면 HttpClientErrorException 이 발생하고 여기에서 메세지가 위처럼 담기는 것이다. 메세지를 받는건 성공했는데 여전히 문제점이 남아 있다. 메세지를 꺼내도 JSON 형태가 아닌 401: [message] 형태로 고정되어 들어온다는 점인데, 401 에러에 한해서는 이렇게 들어온다 하더라도 다른 에러에 대해서는 명확한 핸들링이 현재로썬 불가능하단 점이다.
그래서 어떻게 하면 좋을까 하다가 우선 에러가 발생하면 Error 를 발생하여 HttpClientErrorException에 빠지는 것을 방지하고 아래에서 Status 를 참고하여 처리하면 되겠다 싶었다. 그렇게 될 경우 Response body 에 json 형태로 리턴받지 않을까 싶었다. 그래서 다음 파일을 추가한 다음 RestTemplate 설정에 추가했다.
OauthRestTemplateErrorHandler.java
public class OauthRestTemplateErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = response.getStatusCode();
return statusCode.series() == HttpStatus.Series.SERVER_ERROR;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
...
}
}
RestTemplate 에 설정하기
...
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
restTemplate.setErrorHandler(new OauthRestTemplateErrorHandler());
...
이후 실행해보면 HttpClientErrorException에 빠지는건 더이상 일어나지 않았다. 다만 httpStatus 따른 오류처리를 해줘야 하는데 다음처럼 수행했다.
ResponseEntity<String> response = resTemplate.postForEntity(...);
# 이 부분 추가
if (response.getStatusCode() != HttpStatus.OK) {
// ... 정상이 아닐경우 처리
}
끝.
'공부 > 프로그래밍' 카테고리의 다른 글
[aws] amazon linux2 에 nodejs 설치하기 (0) | 2021.09.24 |
---|---|
[aws, sqs, springboot] fifo 전송 에러 (A queue already exists with the same name and a different ...) (0) | 2021.09.22 |
[springboot, security] ResouceServer에서 HttpBasic에 Exception 핸들링하기 (0) | 2021.08.02 |
[React, PWA] 클라이언트에서 웹 푸시(fcm) 설정하기 (0) | 2021.07.28 |
[springboot] feign 설정하기 (0) | 2021.07.26 |
댓글