diff --git a/build.gradle.kts b/build.gradle.kts index 54d21f454..a8233c340 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,7 @@ java { allprojects { group = "fr.insee.eno" - version = "3.29.1-SNAPSHOT" + version = "3.29.2-SNAPSHOT.4" } subprojects { diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationCustomController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationCustomController.java index 507214355..adad9e2a0 100644 --- a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationCustomController.java +++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationCustomController.java @@ -123,8 +123,7 @@ public ResponseEntity generateXformsCustomParams( addMultipartToBody(multipartBodyBuilder, specificTreatment, "specificTreatment"); // URI uri = xmlControllerUtils.newUriBuilder().path("questionnaire/ddi-2-xforms").build().toUri(); - String outFilename = questionnaireFilename(OutFormat.XFORMS, true); - return xmlControllerUtils.sendPostRequestByte(uri, multipartBodyBuilder, outFilename); + return xmlControllerUtils.sendPostRequestByte(uri, multipartBodyBuilder); } @Operation( @@ -136,7 +135,7 @@ public ResponseEntity generateXformsCustomParams( "You can get a parameters file by using the endpoint `/parameters/xml/{context}/FO`") @PostMapping(value = "ddi-2-fo", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public ResponseEntity generateFOCustomParams( + public ResponseEntity generateFOCustomParams( @RequestPart(value="in") MultipartFile in, @RequestPart(value="params") MultipartFile params, @RequestPart(value="metadata") MultipartFile metadata, @@ -152,8 +151,7 @@ public ResponseEntity generateFOCustomParams( addMultipartToBody(multipartBodyBuilder, specificTreatment, "specificTreatment"); // URI uri = xmlControllerUtils.newUriBuilder().path("questionnaire/ddi-2-fo").build().toUri(); - String outFilename = questionnaireFilename(OutFormat.XFORMS, false); - return xmlControllerUtils.sendPostRequest(uri, multipartBodyBuilder, outFilename); + return xmlControllerUtils.sendPostRequestByte(uri, multipartBodyBuilder); } } diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationStandardController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationStandardController.java index ef26075db..c939e62af 100644 --- a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationStandardController.java +++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationStandardController.java @@ -149,8 +149,7 @@ public ResponseEntity generateXforms( .path("/questionnaire/{context}/xforms") .queryParam("multi-model", multiModel) .build(context); - String outFilename = questionnaireFilename(OutFormat.XFORMS, multiModel); - return xmlControllerUtils.sendPostRequestByte(uri, multipartBodyBuilder, outFilename); + return xmlControllerUtils.sendPostRequestByte(uri, multipartBodyBuilder); } @Operation( @@ -164,7 +163,7 @@ public ResponseEntity generateXforms( "If the multi-model option is set to true, the output questionnaire(s) are put in a zip file." ) @PostMapping(value = "{context}/fo", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public ResponseEntity generateFO( + public ResponseEntity generateFO( @RequestPart(value="in") MultipartFile in, @RequestPart(value="metadata", required = false) MultipartFile metadata, @RequestPart(value="specificTreatment", required=false) MultipartFile specificTreatment, @@ -192,8 +191,7 @@ public ResponseEntity generateFO( .queryParam("Capture", capture) .queryParam("multi-model", multiModel) .build(context); - String outFilename = questionnaireFilename(OutFormat.FO, multiModel); - return xmlControllerUtils.sendPostRequest(uri, multipartBodyBuilder, outFilename); + return xmlControllerUtils.sendPostRequestByte(uri, multipartBodyBuilder); } @Operation( @@ -203,7 +201,7 @@ public ResponseEntity generateFO( "context.") @PostMapping(value = "{context}/fodt", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public ResponseEntity generateFODT( + public ResponseEntity generateFODT( @RequestPart(value="in") MultipartFile in, @PathVariable Context context) throws EnoControllerException { // @@ -211,8 +209,7 @@ public ResponseEntity generateFODT( addMultipartToBody(multipartBodyBuilder, in, "in"); // URI uri = xmlControllerUtils.newUriBuilder().path("/questionnaire/{context}/fodt").build(context); - String outFilename = questionnaireFilename(OutFormat.FODT, false); - return xmlControllerUtils.sendPostRequest(uri, multipartBodyBuilder, outFilename); + return xmlControllerUtils.sendPostRequestByte(uri, multipartBodyBuilder); } } diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationWithMappingController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationWithMappingController.java index eae89f0af..abcf7a7f1 100644 --- a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationWithMappingController.java +++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationWithMappingController.java @@ -61,7 +61,7 @@ public ResponseEntity generate( addMultipartToBody(multipartBodyBuilder, mapping, "mapping"); // URI uri = xmlControllerUtils.newUriBuilder().path("questionnaire/in-2-out").build().toUri(); - String outFilename = multiModel ? "questionnaire.zip" : "questionnaire.txt"; + String outFilename = multiModel ? "questionnaires.zip" : "questionnaire.txt"; return xmlControllerUtils.sendPostRequest(uri, multipartBodyBuilder, outFilename); } diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/exception/EnoExceptionController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/exception/EnoExceptionController.java index 75f467ca1..485e24852 100644 --- a/eno-ws/src/main/java/fr/insee/eno/ws/controller/exception/EnoExceptionController.java +++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/exception/EnoExceptionController.java @@ -3,10 +3,7 @@ import fr.insee.eno.core.exceptions.business.EnoParametersException; import fr.insee.eno.treatments.exceptions.SpecificTreatmentsDeserializationException; import fr.insee.eno.treatments.exceptions.SpecificTreatmentsValidationException; -import fr.insee.eno.ws.exception.ContextException; -import fr.insee.eno.ws.exception.MetadataFileException; -import fr.insee.eno.ws.exception.ModeParameterException; -import fr.insee.eno.ws.exception.MultiModelException; +import fr.insee.eno.ws.exception.*; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -59,6 +56,13 @@ public ResponseEntity exception(IOException ioException) { return new ResponseEntity<>("I/O error: " + ioException.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } + @ExceptionHandler(EnoRedirectionException.class) + public ResponseEntity exception(EnoRedirectionException enoRedirectionException) { + String message = enoRedirectionException.getMessage(); + log.error(message, enoRedirectionException); + return new ResponseEntity<>(message, enoRedirectionException.getHttpStatusCode()); + } + @ExceptionHandler(value = Exception.class) public ResponseEntity exception(Exception exception) { log.error("Unhandled exception thrown in controller: ", exception); diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/utils/EnoXmlControllerUtils.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/utils/EnoXmlControllerUtils.java index 139d98fc5..6b5271436 100644 --- a/eno-ws/src/main/java/fr/insee/eno/ws/controller/utils/EnoXmlControllerUtils.java +++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/utils/EnoXmlControllerUtils.java @@ -1,9 +1,11 @@ package fr.insee.eno.ws.controller.utils; import fr.insee.eno.ws.exception.EnoControllerException; +import fr.insee.eno.ws.exception.EnoRedirectionException; import fr.insee.eno.ws.legacy.parameters.OutFormat; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.client.MultipartBodyBuilder; @@ -60,17 +62,33 @@ public ResponseEntity sendPostRequest(URI uri, MultipartBodyBuilder mult .body(result); } - public ResponseEntity sendPostRequestByte(URI uri, MultipartBodyBuilder multipartBodyBuilder, String outFilename) { - byte[] result = webClient.post() + public ResponseEntity sendPostRequestByte(URI uri, MultipartBodyBuilder multipartBodyBuilder) { + ResponseEntity responseEntity = webClient.post() .uri(uri) .accept(MediaType.APPLICATION_OCTET_STREAM) .contentType(MediaType.MULTIPART_FORM_DATA) .body(BodyInserters.fromMultipartData(multipartBodyBuilder.build())) - .exchangeToMono(clientResponse -> clientResponse.bodyToMono(byte[].class)) + .retrieve() + .onStatus( + HttpStatusCode::is4xxClientError, + clientResponse -> clientResponse.bodyToMono(String.class) + .map(responseBody -> + new EnoRedirectionException(responseBody, clientResponse.statusCode())) + ) + .onStatus( + HttpStatusCode::is5xxServerError, + clientResponse -> clientResponse.bodyToMono(String.class) + .map(responseBody -> + new EnoRedirectionException("Server error: " + responseBody, clientResponse.statusCode())) + ) + .toEntity(byte[].class) .block(); + if (responseEntity == null) + throw new EnoRedirectionException("null result from Eno Xml call."); + String fileName = responseEntity.getHeaders().getContentDisposition().getFilename(); return ResponseEntity.ok() - .headers(HeadersUtils.with(outFilename)) - .body(result); + .headers(HeadersUtils.with(fileName)) + .body(responseEntity.getBody()); } public ResponseEntity sendPostRequest(URI uri) { diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/utils/HeadersUtils.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/utils/HeadersUtils.java index 6302a45bc..03ccf3623 100644 --- a/eno-ws/src/main/java/fr/insee/eno/ws/controller/utils/HeadersUtils.java +++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/utils/HeadersUtils.java @@ -13,5 +13,4 @@ public static HttpHeaders with(String fileName) { headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); return headers; } - } diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/exception/EnoRedirectionException.java b/eno-ws/src/main/java/fr/insee/eno/ws/exception/EnoRedirectionException.java index 45a0ae71a..10189c713 100644 --- a/eno-ws/src/main/java/fr/insee/eno/ws/exception/EnoRedirectionException.java +++ b/eno-ws/src/main/java/fr/insee/eno/ws/exception/EnoRedirectionException.java @@ -1,9 +1,21 @@ package fr.insee.eno.ws.exception; +import lombok.Getter; +import org.springframework.http.HttpStatusCode; + +@Getter public class EnoRedirectionException extends RuntimeException { + private final HttpStatusCode httpStatusCode; + public EnoRedirectionException(String message) { super(message); + httpStatusCode = null; + } + + public EnoRedirectionException(String message, HttpStatusCode httpStatusCode) { + super(message); + this.httpStatusCode = httpStatusCode; } }