복붙노트

[SPRING] HTTP 요청의 리턴 상태가 401 일 때 자바에서 응답 본문을 파싱하는 방법

SPRING

HTTP 요청의 리턴 상태가 401 일 때 자바에서 응답 본문을 파싱하는 방법

Spring의 RestTemplate과 Jackson을 사용하여 RESTful JSON API를 사용하고있다. 경우에 따라 API 제조업체에서 정의한 맞춤 JSON 본문을 사용하여 Status 401 (Unauthorized) 응답을받을 수 있으며 다음과 같이 표시 될 수 있습니다.

{
    "code": 123,
    "message": "Reason for the error"
}

시체를 파싱하고 비즈니스 로직에서 code 속성을 사용해야합니다.

다음은 구문 분석해야하는 오류 응답 Java 객체입니다.

public class CustomError {

    @JsonProperty
    private Integer code;
    @JsonProperty
    private String message;

    public Integer getCode() {
       return code;
    }
    public String getMessage() {
        return message;
    }
}

그리고 이것을 수행하는 커스텀 에러 핸들러 :

public class CustomErrorHandler extends DefaultResponseErrorHandler {
    private RestTemplate restTemplate;
    private ObjectMapper objectMapper;
    private MappingJacksonHttpMessageConverter messageConverter;


    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        return super.hasError(response);
    }

    @Override
    public void handleError(final ClientHttpResponse response) throws IOException {

        try {
            CustomError error = 
                (CustomError) messageConverter.read(CustomError.class, response);
            throw new CustomErrorIOException(error, error.getMessage());
        } catch (Exception e) {
            // parsing failed, resort to default behavior
            super.handleError(response);
        }
    }
}

오류 처리기는 try 블록에서 HttpMessageNotReadableException으로 실패합니다.

이것이 요청을 보내는 방법입니다.

restTemplate.postForObject(url, pojoInstance, responseClass);

Postman과 같은 일반 오래된 클라이언트 프로그램을 사용하여 동일한 요청을 실행하면 예상되는 JSON 응답이 수신됩니다. 그래서 문제는 401의 상태 인 경우 응답 본문에 대한 액세스를 허용하지 않는 Spring의 ClientHttpResponse 구현과 관련 될 수 있다고 가정합니다.

참으로 응답 본문을 파싱 할 수 있습니까?

최신 정보

내가 조사한 것으로부터 RestTemplate 클래스는 ClientHttpResponse를 사용하고, 입력 스트림을 제공하는 sun.net.www.protocol.http.HttpURLConnection을 생성한다. 입력 스트림이 무시되고 IOException이 발생하는 곳은 다음과 같습니다.

따라서 HttpURLConnection의 구현으로 인해 문제가 발생합니다.

이 문제를 피할 수 있습니까? 아마도 우리는 오류 상태 코드의 경우 응답 본문을 무시하지 않는 대체 구현을 사용해야합니까? 어떤 대안을 권할 수 있습니까?

해결법

  1. ==============================

    1.사용자 지정 처리기가 필요없이 다음 방법을 시도하십시오. 아이디어는 HttpStatusCodeException에서 응답을 문자열로 가져온 다음 개체로 변환 할 수 있습니다. 변환을 위해 저는 Jackson의 ObjectMapper를 사용했습니다.

    사용자 지정 처리기가 필요없이 다음 방법을 시도하십시오. 아이디어는 HttpStatusCodeException에서 응답을 문자열로 가져온 다음 개체로 변환 할 수 있습니다. 변환을 위해 저는 Jackson의 ObjectMapper를 사용했습니다.

            try {
    
                restTemplate.postForObject(url, pojoInstance, responseClass);
    
            } catch (HttpStatusCodeException e) {
    
                if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
    
                    String responseString = e.getResponseBodyAsString();
    
                    ObjectMapper mapper = new ObjectMapper();
    
                    CustomError result = mapper.readValue(responseString,
                            CustomError.class);
                }
            }
    

    최신 정보: 다른 팩토리를 사용하면 문제와 관련된 버그가 있기 때문에 도움이 될 수 있습니다 (아래 설명 참조).

    RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
    
  2. from https://stackoverflow.com/questions/26676405/how-to-parse-the-response-body-in-java-when-the-http-request-has-return-status by cc-by-sa and MIT license