diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/route/RouteService.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/route/RouteService.java index 935140e7f37f..3ea4b4cf3805 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/route/RouteService.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/route/RouteService.java @@ -29,6 +29,7 @@ import static org.hisp.dhis.config.HibernateEncryptionConfig.AES_128_STRING_ENCRYPTOR; +import com.fasterxml.jackson.databind.ObjectMapper; import io.netty.handler.timeout.ReadTimeoutException; import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; @@ -57,6 +58,7 @@ import org.jasypt.encryption.pbe.PBEStringCleanablePasswordEncryptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.io.buffer.DataBufferLimitException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -86,6 +88,8 @@ public class RouteService { @Autowired @Getter @Setter private ClientHttpConnector clientHttpConnector; + @Autowired @Getter @Setter private ObjectMapper objectMapper; + private static final Set ALLOWED_REQUEST_HEADERS = Set.of( "accept", @@ -246,6 +250,16 @@ public ResponseEntity execute( .onErrorReturn( throwable -> throwable.getCause() instanceof ReadTimeoutException, new ResponseEntity<>(HttpStatus.GATEWAY_TIMEOUT)) + .onErrorResume( + throwable -> throwable.getCause() instanceof DataBufferLimitException, + throwable -> { + String message = + String.format( + """ +{"message":"%s"}""", + throwable.getCause().getMessage()); + return Mono.just(new ResponseEntity<>(message, HttpStatus.BAD_GATEWAY)); + }) .block(); HttpHeaders responseHeaders = filterResponseHeaders(response.getHeaders()); String responseBody = response.getBody(); diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/RouteControllerTest.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/RouteControllerTest.java index 062b02e9d9fd..19be6b90af07 100644 --- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/RouteControllerTest.java +++ b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/RouteControllerTest.java @@ -31,6 +31,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockserver.model.HttpRequest.request; import com.fasterxml.jackson.core.JsonProcessingException; @@ -141,6 +142,31 @@ public void afterEach() { mockServerClient.reset(); } + @Test + void testRunRouteWhenResponseBodyExceedsLimit() throws JsonProcessingException { + mockServerClient + .when(request().withPath("/")) + .respond(org.mockserver.model.HttpResponse.response("{}")); + + Map route = new HashMap<>(); + route.put("name", "route-under-test"); + route.put("url", "https://dhis2.org"); + + HttpResponse postHttpResponse = POST("/routes", jsonMapper.writeValueAsString(route)); + HttpResponse runHttpResponse = + GET( + "/routes/{id}/run", + postHttpResponse.content().get("response.uid").as(JsonString.class).string()); + + String message = + runHttpResponse + .error(HttpStatus.BAD_GATEWAY) + .get("message") + .as(JsonString.class) + .string(); + assertTrue(message.startsWith("Exceeded limit on max bytes to buffer : ")); + } + @Test void testRunRouteWhenResponseDurationExceedsRouteResponseTimeout() throws JsonProcessingException {