본문 바로가기

Springあるある

API 오류 처리 시 주의할 점!!(Feat. Accept 헤더)

@Slf4j
@Controller
public class ErrorPageController {

    // RequestDispatcher 클래스에 final static으로 정의돼 있음

    public final static String FORWARD_REQUEST_URI = "jakarta.servlet.forward.request_uri";

    public final static String FORWARD_CONTEXT_PATH = "jakarta.servlet.forward.context_path";

    public final static String FORWARD_MAPPING = "jakarta.servlet.forward.mapping";

    public final static String FORWARD_PATH_INFO = "jakarta.servlet.forward.path_info";

    public final static String FORWARD_SERVLET_PATH = "jakarta.servlet.forward.servlet_path";

    public final static String FORWARD_QUERY_STRING = "jakarta.servlet.forward.query_string";

    public final static String INCLUDE_REQUEST_URI = "jakarta.servlet.include.request_uri";

    public final static String INCLUDE_CONTEXT_PATH = "jakarta.servlet.include.context_path";

    public final static String INCLUDE_PATH_INFO = "jakarta.servlet.include.path_info";

    public final static String INCLUDE_MAPPING = "jakarta.servlet.include.mapping";

    public final static String INCLUDE_SERVLET_PATH = "jakarta.servlet.include.servlet_path";

    public final static String INCLUDE_QUERY_STRING = "jakarta.servlet.include.query_string";

    public final static String ERROR_EXCEPTION = "jakarta.servlet.error.exception";

    public final static String ERROR_EXCEPTION_TYPE = "jakarta.servlet.error.exception_type";

    public final static String ERROR_MESSAGE = "jakarta.servlet.error.message";

    public final static String ERROR_REQUEST_URI = "jakarta.servlet.error.request_uri";

    public final static String ERROR_SERVLET_NAME = "jakarta.servlet.error.servlet_name";

    public final static String ERROR_STATUS_CODE = "jakarta.servlet.error.status_code";


    @RequestMapping("/error-page/500")
    public String errorPage500(HttpServletRequest request, HttpServletResponse response){

        log.info("errorPage 500");
        printErrorInfo(request);
        return "error-page/500";

    }
	
    // API 오류 JSON 반환
    @RequestMapping(value="/error-page/500",produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Map<String,Object>> errorPage500Api(HttpServletRequest request,HttpServletResponse response){


        log.info("API Eroor Page : 500");

        HashMap<String, Object> result = new HashMap<>();

        Exception ex = (Exception)request.getAttribute(ERROR_EXCEPTION);
        result.put("message",ex.getMessage());
        result.put("status",request.getAttribute(ERROR_STATUS_CODE));

        Integer statusCode = (Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        return new ResponseEntity<>(result, HttpStatus.valueOf(statusCode));

    }


    private void printErrorInfo(HttpServletRequest request){

        log.info("FORWARD_REQUEST_URI  : {}",request.getAttribute(FORWARD_REQUEST_URI ));
        log.info("FORWARD_CONTEXT_PATH : {}",request.getAttribute(FORWARD_CONTEXT_PATH));
        log.info("FORWARD_MAPPING :{}",request.getAttribute(FORWARD_MAPPING));
        log.info("FORWARD_PATH_INFO : {}",request.getAttribute(FORWARD_PATH_INFO));
        log.info("FORWARD_SERVLET_PATH : {}",request.getAttribute(FORWARD_SERVLET_PATH));
        log.info("FORWARD_QUERY_STRING : {}",request.getAttribute(FORWARD_QUERY_STRING));
        log.info("INCLUDE_REQUEST_URI  : {}",request.getAttribute(INCLUDE_REQUEST_URI ));
        log.info("INCLUDE_CONTEXT_PATH : {}",request.getAttribute(INCLUDE_CONTEXT_PATH));
        log.info("INCLUDE_PATH_INFO  : {}",request.getAttribute(INCLUDE_PATH_INFO ));
        log.info("INCLUDE_MAPPING  : {}",request.getAttribute(INCLUDE_MAPPING ));
        log.info("INCLUDE_SERVLET_PATH : {}",request.getAttribute(INCLUDE_SERVLET_PATH));
        log.info("INCLUDE_QUERY_STRING : {}",request.getAttribute(INCLUDE_QUERY_STRING));
        log.info("ERROR_EXCEPTION: {}",request.getAttribute(ERROR_EXCEPTION ));
        log.info("ERROR_EXCEPTION_TYPE : {}",request.getAttribute(ERROR_EXCEPTION_TYPE));
        log.info("ERROR_MESSAGE  : {}",request.getAttribute(ERROR_MESSAGE ));
        log.info("ERROR_REQUEST_URI : {}",request.getAttribute(ERROR_REQUEST_URI));


        log.info("Dispatcher Type : {}",request.getDispatcherType());


    }






}

 

API는 요청/응답 모두 JSON 형식이여야 한다. 

요청 Http 헤더에 Accept 헤더라는 것이 있다. 

만약 이 Accept 헤더에 "application/json"을 설정하지 않고 모든 반환 타입을 허용하도록 설정(Accept : */*)하게 되면 

위 코드에서 우선 순위의 관계로 errorPage500 메서드가 호출되며 아래의 그림과 같이 API 오류 응답을 HTML로 받게 

돼버려, API를 사용하는 개발자 입장에서 난처하게 된다.(HTML을 일일이 파싱해야 한다)

Accept : */*

 

이를 방지하고자 produecs=MediaType.JSON_VALUE로 설정을 하고 요청 Accept도 application/json으로 설정을 하면

아래와 같이 API 오류 응답을 JSON으로 받을 수가 있다.