[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
This commit is contained in:
Trisha Anand 2021-07-19 19:29:19 +05:30 committed by GitHub
parent 6947f4b7a0
commit 1dfc624a13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 0 deletions

View File

@ -0,0 +1,5 @@
package com.external.constants;
public enum ResponseDataType {
BINARY, IMAGE, TEXT, JSON, UNDEFINED
}

View File

@ -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);