개발

Spring cloud gateway fallback 설정 시 405 응답 발생 이슈

chaani 2025. 4. 25. 18:18

fallback controller를 다음과 같이 만들었는데

일부 요청들에 대한 폴백이 405 응답으로 떨어지는 이슈가 있었다.

@RestController
@RequestMapping("/fallback")
public class GatewayFallbackController {
    
    @GetMapping("/default")
    public ResponseEntity<Mono<FallbackResponse>> fallback(ServerWebExchange exchange) {
        Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
        Exception exception = exchange.getAttribute(CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR);

        String routeId = route != null ? route.getId() : "unknown";
        String errorMessage = exception != null ? exception.getMessage() : "No error info";

        FallbackResponse response = FallbackResponse.builder()
                .status(503)
                .error(routeId + " : " + errorMessage)
                .message("서비스 일시 중단")
                .build();

        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(Mono.just(response));
    }

}

 

405 응답으로 떨어지는 요청들은 모두 GET 요청이 아닌 POST 요청들이었고,

이슈를 재현해보면서 디버깅 해보니

클라이언트에서 POST 요청으로 들어온 요청들은 폴백도 POST 요청을 한다는 점을 발견했다.

 

작성된 코드를 보면 폴백 메소드에 '@GetMapping(~)' 어노테이션이 붙어 있어서 GET 요청만 처리할 수 있었고

POST 요청에 대한 폴백 메소드를 찾을 수 없어 405 응답이 발생했다.

 

그래서 모든 HTTP 메소드에 대응 가능하도록 '@RequestMapping(~)' 어노테이션을 사용하면 된다.

@RestController
@RequestMapping("/fallback")
public class GatewayFallbackController {

    @RequestMapping("/default")
    public ResponseEntity<Mono<FallbackResponse>> fallback(ServerWebExchange exchange) {
        Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
        Exception exception = exchange.getAttribute(CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR);

        String routeId = route != null ? route.getId() : "unknown";
        String errorMessage = exception != null ? exception.getMessage() : "No error info";

        FallbackResponse response = FallbackResponse.builder()
                .status(503)
                .error(routeId + " : " + errorMessage)
                .message("서비스 일시 중단")
                .build();

        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(Mono.just(response));
    }

}