From 1dfc624a13db1fe6961565aebae2c5bf3b15ab77 Mon Sep 17 00:00:00 2001 From: Trisha Anand Date: Mon, 19 Jul 2021 19:29:19 +0530 Subject: [PATCH] [Bug Fix : Rest Api] Base64 encode binary response before sending it out to client (#5958) * 1. For binary data in the response, base64 encoding the same before sending it out on the wire (instead of default conversion to string) 2. Added a new header which sets the data type of the response body. * Minor code reformatting * Fixed failing test cases * The new header created should send the values in an array instead of a single value --- .../external/constants/ResponseDataType.java | 5 ++++ .../com/external/plugins/RestApiPlugin.java | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/constants/ResponseDataType.java diff --git a/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/constants/ResponseDataType.java b/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/constants/ResponseDataType.java new file mode 100644 index 0000000000..18d2dab7d0 --- /dev/null +++ b/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/constants/ResponseDataType.java @@ -0,0 +1,5 @@ +package com.external.constants; + +public enum ResponseDataType { + BINARY, IMAGE, TEXT, JSON, UNDEFINED +} diff --git a/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java b/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java index 5274870725..1f1a32b01c 100644 --- a/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java +++ b/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java @@ -19,10 +19,13 @@ import com.appsmith.external.plugins.SmartSubstitutionInterface; import com.appsmith.external.services.SharedConfig; import com.external.connections.APIConnection; import com.external.connections.APIConnectionFactory; +import com.external.constants.ResponseDataType; import com.external.helpers.BufferingFilter; import com.external.helpers.DataUtils; import com.external.helpers.DatasourceValidator; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; import lombok.extern.slf4j.Slf4j; @@ -84,6 +87,12 @@ public class RestApiPlugin extends BasePlugin { private final String IS_SEND_SESSION_ENABLED_KEY = "isSendSessionEnabled"; private final String SESSION_SIGNATURE_KEY_KEY = "sessionSignatureKey"; private final String SIGNATURE_HEADER_NAME = "X-APPSMITH-SIGNATURE"; + private final String RESPONSE_DATA_TYPE = "X-APPSMITH-DATATYPE"; + private final Set binaryDataTypes = Set.of("application/zip", + "application/octet-stream", + "application/pdf", + "application/pkcs8", + "application/x-binary"); private final SharedConfig sharedConfig; private final DataUtils dataUtils; @@ -351,6 +360,9 @@ public class RestApiPlugin extends BasePlugin { } if (body != null) { + + ResponseDataType responseDataType = ResponseDataType.UNDEFINED; + /**TODO * Handle XML response. Currently we only handle JSON & Image responses. The other kind of responses * are kept as is and returned as a string. @@ -360,6 +372,7 @@ public class RestApiPlugin extends BasePlugin { try { String jsonBody = new String(body, StandardCharsets.UTF_8); result.setBody(objectMapper.readTree(jsonBody)); + responseDataType = ResponseDataType.JSON; } catch (IOException e) { System.out.println("Unable to parse response JSON. Setting response body as string."); String bodyString = new String(body, StandardCharsets.UTF_8); @@ -377,11 +390,25 @@ public class RestApiPlugin extends BasePlugin { MediaType.IMAGE_PNG.equals(contentType)) { String encode = Base64.encode(body); result.setBody(encode); + responseDataType = ResponseDataType.IMAGE; + } else if (binaryDataTypes.contains(contentType.toString())) { + String encode = Base64.encode(body); + result.setBody(encode); + responseDataType = ResponseDataType.BINARY; } else { // If the body is not of JSON type, just set it as is. String bodyString = new String(body, StandardCharsets.UTF_8); result.setBody(bodyString.trim()); + responseDataType = ResponseDataType.TEXT; } + + // Now add a new header which specifies the data type of the response as per Appsmith + JsonNode headersJsonNode = result.getHeaders(); + ObjectNode headersObjectNode = (ObjectNode) headersJsonNode; + headersObjectNode.putArray(RESPONSE_DATA_TYPE) + .add(String.valueOf(responseDataType)); + result.setHeaders(headersObjectNode); + } result.setMessages(hintMessages);