diff --git a/core/src/main/java/org/dcsa/conformance/core/party/ConformanceParty.java b/core/src/main/java/org/dcsa/conformance/core/party/ConformanceParty.java index 4f59d728..89c53b94 100644 --- a/core/src/main/java/org/dcsa/conformance/core/party/ConformanceParty.java +++ b/core/src/main/java/org/dcsa/conformance/core/party/ConformanceParty.java @@ -239,11 +239,11 @@ private JsonNode _syncGetPartyPrompt() { HttpRequest.newBuilder().uri(uri).timeout(Duration.ofHours(1)).GET(); orchestratorAuthHeader.forEach( (name, values) -> values.forEach(value -> httpRequestBuilder.header(name, value))); - String stringResponseBody = + byte[] byteArrayResponseBody = HttpClient.newHttpClient() - .send(httpRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) + .send(httpRequestBuilder.build(), HttpResponse.BodyHandlers.ofByteArray()) .body(); - return new ConformanceMessageBody(stringResponseBody).getJsonBody(); + return new ConformanceMessageBody(byteArrayResponseBody).getJsonBody(); } private void _handleNextActionPrompt() { diff --git a/core/src/main/java/org/dcsa/conformance/core/traffic/ConformanceMessageBody.java b/core/src/main/java/org/dcsa/conformance/core/traffic/ConformanceMessageBody.java index 432777bb..857813b5 100644 --- a/core/src/main/java/org/dcsa/conformance/core/traffic/ConformanceMessageBody.java +++ b/core/src/main/java/org/dcsa/conformance/core/traffic/ConformanceMessageBody.java @@ -1,22 +1,45 @@ package org.dcsa.conformance.core.traffic; +import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import lombok.Getter; import lombok.ToString; -import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; - @Getter @ToString public class ConformanceMessageBody { - private final boolean isCorrectJson; + private final boolean isRawByteArray; + private final byte[] byteArrayBody; private final String stringBody; private final JsonNode jsonBody; + private final boolean isCorrectJson; + + public ConformanceMessageBody(byte[] byteArrayBody) { + this.isRawByteArray = true; + this.byteArrayBody = byteArrayBody == null ? new byte[0] : byteArrayBody; + this.stringBody = new String(this.byteArrayBody, StandardCharsets.UTF_8); + boolean isCorrectJson; + JsonNode jsonBody; + try { + jsonBody = OBJECT_MAPPER.readTree(this.stringBody); + isCorrectJson = true; + } catch (JsonProcessingException e) { + jsonBody = OBJECT_MAPPER.createObjectNode(); + isCorrectJson = false; + } + this.isCorrectJson = isCorrectJson; + this.jsonBody = jsonBody; + } public ConformanceMessageBody(String stringBody) { + this.isRawByteArray = false; this.stringBody = stringBody == null ? "" : stringBody; + this.byteArrayBody = this.stringBody.getBytes(StandardCharsets.UTF_8); boolean isCorrectJson; JsonNode jsonBody; try { @@ -31,15 +54,20 @@ public ConformanceMessageBody(String stringBody) { } public ConformanceMessageBody(JsonNode jsonBody) { + this.isRawByteArray = false; this.isCorrectJson = true; this.jsonBody = jsonBody; this.stringBody = jsonBody.toPrettyString(); + this.byteArrayBody = this.stringBody.getBytes(StandardCharsets.UTF_8); } - public ObjectNode toJson() { + /* package local */ ObjectNode toJson() { ObjectNode objectNode = OBJECT_MAPPER.createObjectNode(); + objectNode.put("isRawByteArray", isRawByteArray); objectNode.put("isCorrectJson", isCorrectJson); - if (isCorrectJson) { + if (isRawByteArray) { + objectNode.put("byteArrayBody", Base64.getEncoder().encodeToString(byteArrayBody)); + } else if (isCorrectJson) { objectNode.set("jsonBody", jsonBody); } else { objectNode.put("stringBody", stringBody); @@ -47,7 +75,11 @@ public ObjectNode toJson() { return objectNode; } - public static ConformanceMessageBody fromJson(ObjectNode objectNode) { + /* package local */ static ConformanceMessageBody fromJson(ObjectNode objectNode) { + boolean isRawByteArray = objectNode.path("isRawByteArray").asBoolean(); + if (isRawByteArray) { + return new ConformanceMessageBody(Base64.getDecoder().decode(objectNode.get("byteArrayBody").asText())); + } boolean isCorrectJson = objectNode.get("isCorrectJson").asBoolean(); if (isCorrectJson) { return new ConformanceMessageBody(objectNode.get("jsonBody")); diff --git a/lambda/src/main/java/org/dcsa/conformance/lambda/ApiLambda.java b/lambda/src/main/java/org/dcsa/conformance/lambda/ApiLambda.java index 27b4a502..ed4c65e7 100644 --- a/lambda/src/main/java/org/dcsa/conformance/lambda/ApiLambda.java +++ b/lambda/src/main/java/org/dcsa/conformance/lambda/ApiLambda.java @@ -4,6 +4,8 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.List; import java.util.Map; @@ -41,7 +43,7 @@ public APIGatewayProxyResponseEvent handleRequest( Objects.requireNonNullElse( event.getMultiValueQueryStringParameters(), Collections.emptyMap()), event.getMultiValueHeaders(), - event.getBody()), + event.getBody().getBytes(StandardCharsets.UTF_8)), LambdaToolkit.createDeferredSandboxTaskConsumer(persistenceProvider)); Map> responseHeaders = conformanceWebResponse.getValueListHeaders(); diff --git a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceOrchestrator.java b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceOrchestrator.java index af170093..92ada032 100644 --- a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceOrchestrator.java +++ b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceOrchestrator.java @@ -195,7 +195,7 @@ public void notifyNextActionParty() { : Map.of( counterpartConfiguration.getAuthHeaderName(), List.of(counterpartConfiguration.getAuthHeaderValue())), - "")); + new byte[]{})); } public JsonNode handleGetPartyPrompt(String partyName) { diff --git a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceSandbox.java b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceSandbox.java index f63259ce..e3552b89 100644 --- a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceSandbox.java +++ b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceSandbox.java @@ -271,7 +271,7 @@ public static ConformanceWebResponse handleRequest( deferredSandboxTaskConsumer, sandboxId, partyName, - webRequest.body()); + webRequest.bodyBytes()); } else if (remainingUri.startsWith("/api")) { return _handlePartyInboundConformanceRequest( persistenceProvider, deferredSandboxTaskConsumer, sandboxId, partyName, webRequest); @@ -469,7 +469,7 @@ private static ConformanceWebResponse _handlePartyInboundConformanceRequest( party.getName(), party.getRole(), webRequest.headers(), - new ConformanceMessageBody(webRequest.body()), + new ConformanceMessageBody(webRequest.bodyBytes()), System.currentTimeMillis())); conformanceRequestReference.set(conformanceRequest); conformanceResponseReference.set(party.handleRequest(conformanceRequest)); @@ -571,9 +571,9 @@ private static ConformanceResponse _syncHttpRequest(ConformanceRequest conforman .message() .headers() .forEach((name, values) -> values.forEach(value -> httpRequestBuilder.header(name, value))); - HttpResponse httpResponse = + HttpResponse httpResponse = HttpClient.newHttpClient() - .send(httpRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + .send(httpRequestBuilder.build(), HttpResponse.BodyHandlers.ofByteArray()); ConformanceResponse conformanceResponse = conformanceRequest.createResponse( httpResponse.statusCode(), @@ -686,7 +686,7 @@ private static ConformanceWebResponse _handlePostPartyInput( Consumer deferredSandboxTaskConsumer, String sandboxId, String partyName, - String input) { + byte[] inputBytes) { new OrchestratorTask( persistenceProvider, conformanceWebRequest -> @@ -695,7 +695,7 @@ private static ConformanceWebResponse _handlePostPartyInput( sandboxId, "handling input from party " + partyName, orchestrator -> - orchestrator.handlePartyInput(new ConformanceMessageBody(input).getJsonBody())) + orchestrator.handlePartyInput(new ConformanceMessageBody(inputBytes).getJsonBody())) .run(); return new ConformanceWebResponse(200, JsonToolkit.JSON_UTF_8, Collections.emptyMap(), "{}"); } diff --git a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceWebRequest.java b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceWebRequest.java index 581277e6..b2985e80 100644 --- a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceWebRequest.java +++ b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceWebRequest.java @@ -2,6 +2,8 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.util.Base64; import java.util.Collection; import java.util.Map; import org.dcsa.conformance.core.toolkit.JsonToolkit; @@ -13,7 +15,7 @@ public record ConformanceWebRequest( String url, Map> queryParameters, Map> headers, - String body) { + byte[] bodyBytes) { public ObjectNode toJson() { ObjectNode objectNode = @@ -21,7 +23,7 @@ public ObjectNode toJson() { .createObjectNode() .put("method", method) .put("url", url) - .put("body", body); + .put("bodyBytes", Base64.getEncoder().encodeToString(bodyBytes)); objectNode.set( "queryParameters", JsonToolkit.mapOfStringToStringCollectionToJson(queryParameters)); objectNode.set("headers", JsonToolkit.mapOfStringToStringCollectionToJson(headers)); @@ -35,6 +37,6 @@ public static ConformanceWebRequest fromJson(ObjectNode objectNode) { JsonToolkit.mapOfStringToStringCollectionFromJson( (ArrayNode) objectNode.get("queryParameters")), JsonToolkit.mapOfStringToStringCollectionFromJson((ArrayNode) objectNode.get("headers")), - objectNode.get("url").asText()); + Base64.getDecoder().decode(objectNode.get("bodyBytes").asText())); } } diff --git a/spring-boot/src/main/java/org/dcsa/conformance/springboot/ConformanceApplication.java b/spring-boot/src/main/java/org/dcsa/conformance/springboot/ConformanceApplication.java index eaa79e2c..df915192 100644 --- a/spring-boot/src/main/java/org/dcsa/conformance/springboot/ConformanceApplication.java +++ b/spring-boot/src/main/java/org/dcsa/conformance/springboot/ConformanceApplication.java @@ -5,6 +5,7 @@ import jakarta.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -214,7 +215,9 @@ public void handleWebuiRequest( persistenceProvider, deferredSandboxTaskConsumer) .handleRequest( - "spring-boot-env", JsonToolkit.stringToJsonNode(_getRequestBody(servletRequest))) + "spring-boot-env", + JsonToolkit.stringToJsonNode( + new String(_getRequestBodyBytes(servletRequest), StandardCharsets.UTF_8))) .toPrettyString()); } @@ -250,7 +253,7 @@ public void handleRequest( requestUrl, _getQueryParameters(servletRequest), requestHeaders, - _getRequestBody(servletRequest)), + _getRequestBodyBytes(servletRequest)), deferredSandboxTaskConsumer); _writeResponse( @@ -294,8 +297,8 @@ private static void _writeResponse( } @SneakyThrows - private static String _getRequestBody(HttpServletRequest request) { - return request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); + private static byte[] _getRequestBodyBytes(HttpServletRequest request) { + return request.getInputStream().readAllBytes(); } @GetMapping(value = "/")