From 767fe7cdab0138cf47020cf35cb5145281209ac7 Mon Sep 17 00:00:00 2001 From: skyflow-himanshu Date: Fri, 30 Jan 2026 12:40:36 +0530 Subject: [PATCH 01/10] SK-2519: extract hard coded strings to constants and update linting rules --- checkstyle.xml | 45 +++- pom.xml | 2 +- src/main/java/com/skyflow/VaultClient.java | 4 +- .../java/com/skyflow/errors/ErrorMessage.java | 1 + .../com/skyflow/errors/SkyflowException.java | 10 +- .../serviceaccount/util/BearerToken.java | 30 +-- .../serviceaccount/util/SignedDataTokens.java | 27 +-- .../skyflow/serviceaccount/util/Token.java | 3 +- .../java/com/skyflow/utils/Constants.java | 206 +++++++++++++++++- .../java/com/skyflow/utils/HttpUtility.java | 32 +-- src/main/java/com/skyflow/utils/Utils.java | 10 +- .../utils/validations/Validations.java | 8 +- .../controller/ConnectionController.java | 4 +- .../vault/controller/DetectController.java | 42 ++-- .../vault/controller/VaultController.java | 26 +-- .../skyflow/vault/data/DeleteResponse.java | 3 +- .../com/skyflow/vault/data/QueryResponse.java | 9 +- .../skyflow/vault/data/UpdateResponse.java | 7 +- .../vault/tokens/DetokenizeResponse.java | 11 +- .../vault/tokens/TokenizeResponse.java | 9 +- 20 files changed, 372 insertions(+), 117 deletions(-) diff --git a/checkstyle.xml b/checkstyle.xml index d7ff94b0..da314b9a 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -16,5 +16,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/pom.xml b/pom.xml index 7c7121b5..c9e7f47f 100644 --- a/pom.xml +++ b/pom.xml @@ -200,7 +200,7 @@ false true - **/generated/** + **/generated/**,**/logs/** diff --git a/src/main/java/com/skyflow/VaultClient.java b/src/main/java/com/skyflow/VaultClient.java index b6974f5d..b89bdad9 100644 --- a/src/main/java/com/skyflow/VaultClient.java +++ b/src/main/java/com/skyflow/VaultClient.java @@ -808,9 +808,9 @@ private TokenTypeMapping buildTokenType(TokenFormat tokenFormat, private FileDataDeidentifyAudioDataFormat mapAudioDataFormat(String dataFormat) throws SkyflowException { switch (dataFormat) { - case "mp3": + case Constants.FileFormatType.MP3: return FileDataDeidentifyAudioDataFormat.MP_3; - case "wav": + case Constants.FileFormatType.WAV: return FileDataDeidentifyAudioDataFormat.WAV; default: throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidAudioFileType.getMessage()); diff --git a/src/main/java/com/skyflow/errors/ErrorMessage.java b/src/main/java/com/skyflow/errors/ErrorMessage.java index ac6adfd0..c20df57c 100644 --- a/src/main/java/com/skyflow/errors/ErrorMessage.java +++ b/src/main/java/com/skyflow/errors/ErrorMessage.java @@ -2,6 +2,7 @@ import com.skyflow.utils.Constants; +@SuppressWarnings("checkstyle:MultipleStringLiterals") public enum ErrorMessage { // Client initialization VaultIdAlreadyInConfigList("%s0 Validation error. VaultId is present in an existing config. Specify a new vaultId in config."), diff --git a/src/main/java/com/skyflow/errors/SkyflowException.java b/src/main/java/com/skyflow/errors/SkyflowException.java index 32c71f39..849ce3c5 100644 --- a/src/main/java/com/skyflow/errors/SkyflowException.java +++ b/src/main/java/com/skyflow/errors/SkyflowException.java @@ -57,7 +57,7 @@ public SkyflowException(int httpCode, Throwable cause, Map> private void setResponseBody(String responseBody, Map> responseHeaders) { this.responseBody = JsonParser.parseString(responseBody).getAsJsonObject(); - if (this.responseBody.get("error") != null) { + if (this.responseBody.get(Constants.JsonFieldNames.ERROR) != null) { setGrpcCode(); setHttpStatus(); setMessage(); @@ -75,17 +75,17 @@ private void setRequestId(Map> responseHeaders) { } private void setMessage() { - JsonElement messageElement = ((JsonObject) responseBody.get("error")).get("message"); + JsonElement messageElement = ((JsonObject) responseBody.get(Constants.JsonFieldNames.ERROR)).get(Constants.JsonFieldNames.MESSAGE); this.message = messageElement == null ? null : messageElement.getAsString(); } private void setGrpcCode() { - JsonElement grpcElement = ((JsonObject) responseBody.get("error")).get("grpc_code"); + JsonElement grpcElement = ((JsonObject) responseBody.get(Constants.JsonFieldNames.ERROR)).get(Constants.JsonFieldNames.GRPC_CODE); this.grpcCode = grpcElement == null ? null : grpcElement.getAsInt(); } private void setHttpStatus() { - JsonElement statusElement = ((JsonObject) responseBody.get("error")).get("http_status"); + JsonElement statusElement = ((JsonObject) responseBody.get(Constants.JsonFieldNames.ERROR)).get(Constants.JsonFieldNames.HTTP_STATUS); this.httpStatus = statusElement == null ? null : statusElement.getAsString(); } @@ -98,7 +98,7 @@ public JsonArray getDetails() { } private void setDetails(Map> responseHeaders) { - JsonElement detailsElement = ((JsonObject) responseBody.get("error")).get("details"); + JsonElement detailsElement = ((JsonObject) responseBody.get(Constants.JsonFieldNames.ERROR)).get(Constants.JsonFieldNames.DETAILS); List errorFromClientHeader = responseHeaders.get(Constants.ERROR_FROM_CLIENT_HEADER_KEY); if (detailsElement != null) { this.details = detailsElement.getAsJsonArray(); diff --git a/src/main/java/com/skyflow/serviceaccount/util/BearerToken.java b/src/main/java/com/skyflow/serviceaccount/util/BearerToken.java index 21000f0f..a2bfcdc3 100644 --- a/src/main/java/com/skyflow/serviceaccount/util/BearerToken.java +++ b/src/main/java/com/skyflow/serviceaccount/util/BearerToken.java @@ -92,25 +92,25 @@ private static V1GetAuthTokenResponse getBearerTokenFromCredentials( JsonObject credentials, String context, ArrayList roles ) throws SkyflowException { try { - JsonElement privateKey = credentials.get("privateKey"); + JsonElement privateKey = credentials.get(Constants.CredentialFields.PRIVATE_KEY); if (privateKey == null) { LogUtil.printErrorLog(ErrorLogs.PRIVATE_KEY_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.MissingPrivateKey.getMessage()); } - JsonElement clientID = credentials.get("clientID"); + JsonElement clientID = credentials.get(Constants.CredentialFields.CLIENT_ID); if (clientID == null) { LogUtil.printErrorLog(ErrorLogs.CLIENT_ID_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.MissingClientId.getMessage()); } - JsonElement keyID = credentials.get("keyID"); + JsonElement keyID = credentials.get(Constants.CredentialFields.KEY_ID); if (keyID == null) { LogUtil.printErrorLog(ErrorLogs.KEY_ID_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.MissingKeyId.getMessage()); } - JsonElement tokenURI = credentials.get("tokenURI"); + JsonElement tokenURI = credentials.get(Constants.CredentialFields.TOKEN_URI); if (tokenURI == null) { LogUtil.printErrorLog(ErrorLogs.TOKEN_URI_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.MissingTokenUri.getMessage()); @@ -123,7 +123,7 @@ private static V1GetAuthTokenResponse getBearerTokenFromCredentials( String basePath = Utils.getBaseURL(tokenURI.getAsString()); API_CLIENT_BUILDER.url(basePath); - ApiClient apiClient = API_CLIENT_BUILDER.token("token").build(); + ApiClient apiClient = API_CLIENT_BUILDER.token(Constants.ApiToken.TOKEN).build(); AuthenticationClient authenticationApi = apiClient.authentication(); V1GetAuthTokenRequest._FinalStage authTokenBuilder = V1GetAuthTokenRequest.builder().grantType(Constants.GRANT_TYPE).assertion(signedUserJWT); @@ -149,11 +149,11 @@ private static String getSignedToken( final Date createdDate = new Date(); final Date expirationDate = new Date(createdDate.getTime() + (3600 * 1000)); return Jwts.builder() - .claim("iss", clientID) - .claim("key", keyID) - .claim("aud", tokenURI) - .claim("sub", clientID) - .claim("ctx", context) + .claim(Constants.JwtClaims.ISS, clientID) + .claim(Constants.JwtClaims.KEY, keyID) + .claim(Constants.JwtClaims.AUD, tokenURI) + .claim(Constants.JwtClaims.SUB, clientID) + .claim(Constants.JwtClaims.CTX, context) .expiration(expirationDate) .signWith(pvtKey, Jwts.SIG.RS256) .compact(); @@ -163,7 +163,7 @@ private static String getScopeUsingRoles(ArrayList roles) { StringBuilder scope = new StringBuilder(); if (roles != null) { for (String role : roles) { - scope.append(" role:").append(role); + scope.append(Constants.ApiToken.ROLE_PREFIX).append(role); } } return scope.toString(); @@ -173,10 +173,10 @@ public synchronized String getBearerToken() throws SkyflowException { LogUtil.printInfoLog(InfoLogs.GET_BEARER_TOKEN_TRIGGERED.getLog()); V1GetAuthTokenResponse response; String accessToken = null; - if (this.credentialsFile != null && Objects.equals(this.credentialsType, "FILE")) { + if (this.credentialsFile != null && Objects.equals(this.credentialsType, Constants.CredentialTypeValues.FILE)) { response = generateBearerTokenFromCredentials(this.credentialsFile, this.ctx, this.roles); accessToken = response.getAccessToken().get(); - } else if (this.credentialsString != null && Objects.equals(this.credentialsType, "STRING")) { + } else if (this.credentialsString != null && Objects.equals(this.credentialsType, Constants.CredentialTypeValues.STRING)) { response = generateBearerTokenFromCredentialString(this.credentialsString, this.ctx, this.roles); accessToken = response.getAccessToken().get(); } @@ -200,13 +200,13 @@ private void setCredentialsType(String credentialsType) { } public BearerTokenBuilder setCredentials(File credentialsFile) { - setCredentialsType("FILE"); + setCredentialsType(Constants.CredentialTypeValues.FILE); this.credentialsFile = credentialsFile; return this; } public BearerTokenBuilder setCredentials(String credentialsString) { - setCredentialsType("STRING"); + setCredentialsType(Constants.CredentialTypeValues.STRING); this.credentialsString = credentialsString; return this; } diff --git a/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java b/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java index 70a5a330..883dfbc9 100644 --- a/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java +++ b/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokens.java @@ -9,6 +9,7 @@ import com.skyflow.errors.SkyflowException; import com.skyflow.logs.ErrorLogs; import com.skyflow.logs.InfoLogs; +import com.skyflow.utils.Constants; import com.skyflow.utils.Utils; import com.skyflow.utils.logger.LogUtil; import io.jsonwebtoken.Jwts; @@ -93,19 +94,19 @@ private static List generateSignedTokensFromCredentials ) throws SkyflowException { List signedDataTokens = null; try { - JsonElement privateKey = credentials.get("privateKey"); + JsonElement privateKey = credentials.get(Constants.CredentialFields.PRIVATE_KEY); if (privateKey == null) { LogUtil.printErrorLog(ErrorLogs.PRIVATE_KEY_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.MissingPrivateKey.getMessage()); } - JsonElement clientID = credentials.get("clientID"); + JsonElement clientID = credentials.get(Constants.CredentialFields.CLIENT_ID); if (clientID == null) { LogUtil.printErrorLog(ErrorLogs.CLIENT_ID_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.MissingClientId.getMessage()); } - JsonElement keyID = credentials.get("keyID"); + JsonElement keyID = credentials.get(Constants.CredentialFields.KEY_ID); if (keyID == null) { LogUtil.printErrorLog(ErrorLogs.KEY_ID_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.MissingKeyId.getMessage()); @@ -136,12 +137,12 @@ private static List getSignedToken( List list = new ArrayList<>(); for (String dataToken : dataTokens) { String eachSignedDataToken = Jwts.builder() - .claim("iss", "sdk") - .claim("iat", (createdDate.getTime() / 1000)) - .claim("key", keyID) - .claim("sub", clientID) - .claim("ctx", context) - .claim("tok", dataToken) + .claim(Constants.JwtClaims.ISS, Constants.JwtClaims.SDK) + .claim(Constants.JwtClaims.IAT, (createdDate.getTime() / 1000)) + .claim(Constants.JwtClaims.KEY, keyID) + .claim(Constants.JwtClaims.SUB, clientID) + .claim(Constants.JwtClaims.CTX, context) + .claim(Constants.JwtClaims.TOK, dataToken) .expiration(expirationDate) .signWith(pvtKey, Jwts.SIG.RS256) .compact(); @@ -154,9 +155,9 @@ private static List getSignedToken( public synchronized List getSignedDataTokens() throws SkyflowException { LogUtil.printInfoLog(InfoLogs.GET_SIGNED_DATA_TOKENS_TRIGGERED.getLog()); List signedToken = new ArrayList<>(); - if (this.credentialsFile != null && Objects.equals(this.credentialsType, "FILE")) { + if (this.credentialsFile != null && Objects.equals(this.credentialsType, Constants.CredentialTypeValues.FILE)) { signedToken = generateSignedTokenFromCredentialsFile(this.credentialsFile, this.dataTokens, this.timeToLive, this.ctx); - } else if (this.credentialsString != null && Objects.equals(this.credentialsType, "STRING")) { + } else if (this.credentialsString != null && Objects.equals(this.credentialsType, Constants.CredentialTypeValues.STRING)) { signedToken = generateSignedTokensFromCredentialsString(this.credentialsString, this.dataTokens, this.timeToLive, this.ctx); } LogUtil.printInfoLog(InfoLogs.GET_SIGNED_DATA_TOKEN_SUCCESS.getLog()); @@ -179,13 +180,13 @@ private void setCredentialsType(String credentialsType) { } public SignedDataTokensBuilder setCredentials(File credentialsFile) { - setCredentialsType("FILE"); + setCredentialsType(Constants.CredentialTypeValues.FILE); this.credentialsFile = credentialsFile; return this; } public SignedDataTokensBuilder setCredentials(String credentialsString) { - setCredentialsType("STRING"); + setCredentialsType(Constants.CredentialTypeValues.STRING); this.credentialsString = credentialsString; return this; } diff --git a/src/main/java/com/skyflow/serviceaccount/util/Token.java b/src/main/java/com/skyflow/serviceaccount/util/Token.java index 90da0cf4..d015a9c8 100644 --- a/src/main/java/com/skyflow/serviceaccount/util/Token.java +++ b/src/main/java/com/skyflow/serviceaccount/util/Token.java @@ -8,6 +8,7 @@ import com.skyflow.errors.SkyflowException; import com.skyflow.logs.ErrorLogs; import com.skyflow.logs.InfoLogs; +import com.skyflow.utils.Constants; import com.skyflow.utils.logger.LogUtil; import org.apache.commons.codec.binary.Base64; @@ -25,7 +26,7 @@ public static boolean isExpired(String token) { } currentTime = new Date().getTime() / 1000; - expiryTime = decoded(token).get("exp").getAsLong(); + expiryTime = decoded(token).get(Constants.JsonFieldNames.EXP).getAsLong(); } catch (JsonSyntaxException | SkyflowException e) { LogUtil.printErrorLog(ErrorLogs.INVALID_BEARER_TOKEN.getLog()); diff --git a/src/main/java/com/skyflow/utils/Constants.java b/src/main/java/com/skyflow/utils/Constants.java index 6af03281..1f26cd9d 100644 --- a/src/main/java/com/skyflow/utils/Constants.java +++ b/src/main/java/com/skyflow/utils/Constants.java @@ -10,6 +10,7 @@ public final class Constants { public static final String STAGE_DOMAIN = ".vault.skyflowapis.tech"; public static final String SANDBOX_DOMAIN = ".vault.skyflowapis-preview.com"; public static final String PROD_DOMAIN = ".vault.skyflowapis.com"; + public static final String HTTPS_PROTOCOL = "https"; public static final String PKCS8_PRIVATE_HEADER = "-----BEGIN PRIVATE KEY-----"; public static final String PKCS8_PRIVATE_FOOTER = "-----END PRIVATE KEY-----"; public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer"; @@ -30,9 +31,212 @@ public final class Constants { public static final String SDK_AUTH_HEADER_KEY = "x-skyflow-authorization"; public static final String SDK_METRICS_HEADER_KEY = "sky-metadata"; public static final String REQUEST_ID_HEADER_KEY = "x-request-id"; - public static final String PROCESSED_FILE_NAME_PREFIX = "processed-"; public static final String ERROR_FROM_CLIENT_HEADER_KEY = "error-from-client"; + public static final String PROCESSED_FILE_NAME_PREFIX = "processed-"; public static final String DEIDENTIFIED_FILE_PREFIX = "deidentified"; + public static final class HttpHeader { + public static final String CONTENT_TYPE = "content-type"; + public static final String CONTENT_TYPE_JSON = "application/json"; + public static final String CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded"; + public static final String CONTENT_TYPE_MULTIPART = "multipart/form-data"; + public static final String ACCEPT = "Accept"; + public static final String ACCEPT_ALL = "*/*"; + public static final String CONTENT_DISPOSITION = "Content-Disposition"; + public static final String BOUNDARY_SEPARATOR = "; boundary="; + public static final String FORM_DATA_HEADER = ": form-data; name=\""; + + private HttpHeader() { + // Utility class constructor + } + } + + public static final class EncodingType { + public static final String BASE64 = "base64"; + public static final String UTF_8 = "utf-8"; + public static final String BINARY = "binary"; + public static final String UTF_8_CHARSET = "UTF-8"; + + private EncodingType() { + // Utility class constructor + } + } + + public static final class FileFormatType { + public static final String TXT = "txt"; + public static final String MP3 = "mp3"; + public static final String WAV = "wav"; + public static final String PDF = "pdf"; + public static final String JPG = "jpg"; + public static final String JPEG = "jpeg"; + public static final String PNG = "png"; + public static final String BMP = "bmp"; + public static final String TIF = "tif"; + public static final String TIFF = "tiff"; + public static final String PPT = "ppt"; + public static final String PPTX = "pptx"; + public static final String CSV = "csv"; + public static final String XLS = "xls"; + public static final String XLSX = "xlsx"; + public static final String DOC = "doc"; + public static final String DOCX = "docx"; + public static final String JSON = "json"; + public static final String XML = "xml"; + + private FileFormatType() { + // Utility class constructor + } + } + + public static final class DetectStatus { + public static final String SUCCESS = "SUCCESS"; + public static final String FAILED = "FAILED"; + public static final String IN_PROGRESS = "IN_PROGRESS"; + + private DetectStatus() { + // Utility class constructor + } + } + + public static final class FileProcessing { + public static final String ENTITIES = "entities"; + + private FileProcessing() { + // Utility class constructor + } + } + + public static final class FieldNames { + public static final String SKYFLOW_ID_CAMEL = "skyflowId"; + public static final String TOKENIZED_DATA = "tokenizedData"; + + private FieldNames() { + // Utility class constructor + } + } + + public static final class FormData { + public static final String BOUNDARY_SEPARATOR = "--"; + + private FormData() { + // Utility class constructor + } + } + + public static final class JsonFieldNames { + public static final String ERROR = "error"; + public static final String MESSAGE = "message"; + public static final String GRPC_CODE = "grpc_code"; + public static final String HTTP_STATUS = "http_status"; + public static final String DETAILS = "details"; + public static final String BODY = "Body"; + public static final String TOKENS = "tokens"; + public static final String RECORDS = "records"; + public static final String FIELDS = "fields"; + public static final String VALUE = "value"; + public static final String ERRORS = "errors"; + public static final String TYPE = "type"; + public static final String UPDATED_FIELD = "updatedField"; + public static final String REQUEST_INDEX = "requestIndex"; + public static final String HTTP_CODE = "httpCode"; + public static final String REQUEST_ID = "requestId"; + public static final String EXP = "exp"; + public static final String SKYFLOW_ID = "skyflow_id"; + + private JsonFieldNames() { + // Utility class constructor + } + } + + public static final class CredentialFields { + public static final String PRIVATE_KEY = "privateKey"; + public static final String CLIENT_ID = "clientID"; + public static final String KEY_ID = "keyID"; + public static final String TOKEN_URI = "tokenURI"; + + private CredentialFields() { + // Utility class constructor + } + } + + public static final class JwtClaims { + public static final String ISS = "iss"; + public static final String KEY = "key"; + public static final String AUD = "aud"; + public static final String SUB = "sub"; + public static final String CTX = "ctx"; + public static final String IAT = "iat"; + public static final String TOK = "tok"; + public static final String SDK = "sdk"; + + private JwtClaims() { + // Utility class constructor + } + } + + public static final class ApiToken { + public static final String TOKEN = "token"; + public static final String ROLE_PREFIX = " role:"; + + private ApiToken() { + // Utility class constructor + } + } + + public static final class CredentialTypeValues { + public static final String FILE = "FILE"; + public static final String STRING = "STRING"; + + private CredentialTypeValues() { + // Utility class constructor + } + } + + public static final class CryptoAlgorithm { + public static final String RSA = "RSA"; + + private CryptoAlgorithm() { + // Utility class constructor + } + } + + public static final class HttpUtility { + public static final String FORM_ENCODE_SEPARATOR = "="; + public static final String FORM_ENCODE_DELIMITER = "&"; + public static final String REQUEST_ID_DELIMITER = ","; + public static final String REQUEST_ID_PREFIX = " - requestId: "; + public static final String ERROR_DESCRIPTION = "replace with description"; + + private HttpUtility() { + // Utility class constructor + } + } + + public static final class SystemProperty { + public static final String OS_NAME = "os.name"; + public static final String OS_VERSION = "os.version"; + public static final String JAVA_VERSION = "java.version"; + public static final String JAVA_TEMP_DIR = "java.io.tmpdir"; + + private SystemProperty() { + // Utility class constructor + } + } + + public static final class UrlFormat { + public static final String PROTOCOL_HOST_FORMAT = "%s://%s"; + + private UrlFormat() { + // Utility class constructor + } + } + + public static final class FileExtension { + public static final String JSON = ".json"; + + private FileExtension() { + // Utility class constructor + } + } static { String sdkVersion; diff --git a/src/main/java/com/skyflow/utils/HttpUtility.java b/src/main/java/com/skyflow/utils/HttpUtility.java index b8e9283b..9c8aaf6d 100644 --- a/src/main/java/com/skyflow/utils/HttpUtility.java +++ b/src/main/java/com/skyflow/utils/HttpUtility.java @@ -32,17 +32,17 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< try { connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod(method); - connection.setRequestProperty("content-type", "application/json"); - connection.setRequestProperty("Accept", "*/*"); + connection.setRequestProperty(Constants.HttpHeader.CONTENT_TYPE, Constants.HttpHeader.CONTENT_TYPE_JSON); + connection.setRequestProperty(Constants.HttpHeader.ACCEPT, Constants.HttpHeader.ACCEPT_ALL); if (headers != null && !headers.isEmpty()) { for (Map.Entry entry : headers.entrySet()) connection.setRequestProperty(entry.getKey(), entry.getValue()); // append dynamic boundary if content-type is multipart/form-data - if (headers.containsKey("content-type")) { - if (Objects.equals(headers.get("content-type"), "multipart/form-data")) { - connection.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary); + if (headers.containsKey(Constants.HttpHeader.CONTENT_TYPE)) { + if (Objects.equals(headers.get(Constants.HttpHeader.CONTENT_TYPE), Constants.HttpHeader.CONTENT_TYPE_MULTIPART)) { + connection.setRequestProperty(Constants.HttpHeader.CONTENT_TYPE, Constants.HttpHeader.CONTENT_TYPE_MULTIPART + Constants.HttpHeader.BOUNDARY_SEPARATOR + boundary); } } } @@ -50,11 +50,11 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< connection.setDoOutput(true); try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) { byte[] input = null; - String requestContentType = connection.getRequestProperty("content-type"); + String requestContentType = connection.getRequestProperty(Constants.HttpHeader.CONTENT_TYPE); - if (requestContentType.contains("application/x-www-form-urlencoded")) { + if (requestContentType.contains(Constants.HttpHeader.CONTENT_TYPE_FORM_URLENCODED)) { input = formatJsonToFormEncodedString(params).getBytes(StandardCharsets.UTF_8); - } else if (requestContentType.contains("multipart/form-data")) { + } else if (requestContentType.contains(Constants.HttpHeader.CONTENT_TYPE_MULTIPART)) { input = formatJsonToMultiPartFormDataString(params, boundary).getBytes(StandardCharsets.UTF_8); } else { input = params.toString().getBytes(StandardCharsets.UTF_8); @@ -66,15 +66,15 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< } int httpCode = connection.getResponseCode(); - String requestID = connection.getHeaderField("x-request-id"); - HttpUtility.requestID = requestID.split(",")[0]; + String requestID = connection.getHeaderField(Constants.REQUEST_ID_HEADER_KEY); + HttpUtility.requestID = requestID.split(Constants.HttpUtility.REQUEST_ID_DELIMITER)[0]; Map> responseHeaders = connection.getHeaderFields(); Reader streamReader; if (httpCode > 299) { if (connection.getErrorStream() != null) streamReader = new InputStreamReader(connection.getErrorStream()); else { - String description = appendRequestId("replace with description", requestID); + String description = appendRequestId(Constants.HttpUtility.ERROR_DESCRIPTION, requestID); throw new SkyflowException(description); } } else { @@ -121,7 +121,7 @@ public static String formatJsonToMultiPartFormDataString(JsonObject requestBody, formEncodeString.append(makeFormDataKeyValuePair(currentEntry.getKey(), currentEntry.getValue(), boundary)); formEncodeString.append(LINE_FEED); - formEncodeString.append("--").append(boundary).append("--").append(LINE_FEED); + formEncodeString.append(Constants.FormData.BOUNDARY_SEPARATOR).append(boundary).append(Constants.FormData.BOUNDARY_SEPARATOR).append(LINE_FEED); return formEncodeString.toString(); } @@ -143,8 +143,8 @@ private static HashMap convertJsonToMap(JsonObject json, String private static String makeFormDataKeyValuePair(String key, String value, String boundary) { StringBuilder formDataTextField = new StringBuilder(); - formDataTextField.append("--").append(boundary).append(LINE_FEED); - formDataTextField.append("Content-Disposition: form-data; name=\"").append(key).append("\"").append(LINE_FEED); + formDataTextField.append(Constants.FormData.BOUNDARY_SEPARATOR).append(boundary).append(LINE_FEED); + formDataTextField.append(Constants.HttpHeader.CONTENT_DISPOSITION).append(Constants.HttpHeader.FORM_DATA_HEADER).append(key).append("\"").append(LINE_FEED); formDataTextField.append(LINE_FEED); formDataTextField.append(value).append(LINE_FEED); @@ -153,13 +153,13 @@ private static String makeFormDataKeyValuePair(String key, String value, String public static String appendRequestId(String message, String requestId) { if (requestId != null && !requestId.isEmpty()) { - message = message + " - requestId: " + requestId; + message = message + Constants.HttpUtility.REQUEST_ID_PREFIX + requestId; } return message; } private static String makeFormEncodeKeyValuePair(String key, String value) { - return key + "=" + value + "&"; + return key + Constants.HttpUtility.FORM_ENCODE_SEPARATOR + value + Constants.HttpUtility.FORM_ENCODE_DELIMITER; } } diff --git a/src/main/java/com/skyflow/utils/Utils.java b/src/main/java/com/skyflow/utils/Utils.java index 165c6a80..763380ab 100644 --- a/src/main/java/com/skyflow/utils/Utils.java +++ b/src/main/java/com/skyflow/utils/Utils.java @@ -93,7 +93,7 @@ public static String getBaseURL(String url) throws MalformedURLException { URL parsedUrl = new URL(url); String protocol = parsedUrl.getProtocol(); String host = parsedUrl.getHost(); - return String.format("%s://%s", protocol, host); + return String.format(Constants.UrlFormat.PROTOCOL_HOST_FORMAT, protocol, host); } public static String parameterizedString(String base, String... args) { @@ -145,7 +145,7 @@ public static JsonObject getMetrics() { String javaVersion; // Retrieve device model try { - deviceModel = System.getProperty("os.name"); + deviceModel = System.getProperty(Constants.SystemProperty.OS_NAME); if (deviceModel == null) throw new Exception(); } catch (Exception e) { LogUtil.printInfoLog(parameterizedString( @@ -157,7 +157,7 @@ public static JsonObject getMetrics() { // Retrieve OS details try { - osDetails = System.getProperty("os.version"); + osDetails = System.getProperty(Constants.SystemProperty.OS_VERSION); if (osDetails == null) throw new Exception(); } catch (Exception e) { LogUtil.printInfoLog(parameterizedString( @@ -169,7 +169,7 @@ public static JsonObject getMetrics() { // Retrieve Java version details try { - javaVersion = System.getProperty("java.version"); + javaVersion = System.getProperty(Constants.SystemProperty.JAVA_VERSION); if (javaVersion == null) throw new Exception(); } catch (Exception e) { LogUtil.printInfoLog(parameterizedString( @@ -190,7 +190,7 @@ private static PrivateKey parsePkcs8PrivateKey(byte[] pkcs8Bytes) throws Skyflow PrivateKey privateKey = null; try { PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8Bytes); - keyFactory = KeyFactory.getInstance("RSA"); + keyFactory = KeyFactory.getInstance(Constants.CryptoAlgorithm.RSA); privateKey = keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { LogUtil.printErrorLog(ErrorLogs.INVALID_ALGORITHM.getLog()); diff --git a/src/main/java/com/skyflow/utils/validations/Validations.java b/src/main/java/com/skyflow/utils/validations/Validations.java index 0372749a..31ee00e0 100644 --- a/src/main/java/com/skyflow/utils/validations/Validations.java +++ b/src/main/java/com/skyflow/utils/validations/Validations.java @@ -513,17 +513,17 @@ public static void validateUpdateRequest(UpdateRequest updateRequest) throws Sky ErrorLogs.EMPTY_DATA.getLog(), InterfaceName.UPDATE.getName() )); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyData.getMessage()); - } else if (!data.containsKey("skyflow_id")) { + } else if (!data.containsKey(Constants.JsonFieldNames.SKYFLOW_ID)) { LogUtil.printErrorLog(Utils.parameterizedString( ErrorLogs.SKYFLOW_ID_IS_REQUIRED.getLog(), InterfaceName.UPDATE.getName() )); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.SkyflowIdKeyError.getMessage()); - } else if (!(data.get("skyflow_id") instanceof String)) { + } else if (!(data.get(Constants.JsonFieldNames.SKYFLOW_ID) instanceof String)) { LogUtil.printErrorLog(Utils.parameterizedString( ErrorLogs.INVALID_SKYFLOW_ID_TYPE.getLog(), InterfaceName.UPDATE.getName() )); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidSkyflowIdType.getMessage()); - } else if (data.get("skyflow_id").toString().trim().isEmpty()) { + } else if (data.get(Constants.JsonFieldNames.SKYFLOW_ID).toString().trim().isEmpty()) { LogUtil.printErrorLog(Utils.parameterizedString( ErrorLogs.EMPTY_SKYFLOW_ID.getLog(), InterfaceName.UPDATE.getName() )); @@ -800,7 +800,7 @@ public static void validateReidentifyTextRequest(ReidentifyTextRequest reidentif private static boolean isInvalidURL(String configURL) { try { URL url = new URL(configURL); - if (!url.getProtocol().equals("https")) throw new Exception(); + if (!url.getProtocol().equals(Constants.HTTPS_PROTOCOL)) throw new Exception(); } catch (Exception e) { return true; } diff --git a/src/main/java/com/skyflow/vault/controller/ConnectionController.java b/src/main/java/com/skyflow/vault/controller/ConnectionController.java index 4a9334d4..e1aff01b 100644 --- a/src/main/java/com/skyflow/vault/controller/ConnectionController.java +++ b/src/main/java/com/skyflow/vault/controller/ConnectionController.java @@ -66,7 +66,7 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR String response = HttpUtility.sendRequest(requestMethod.name(), new URL(filledURL), requestBody, headers); JsonObject data = JsonParser.parseString(response).getAsJsonObject(); HashMap metadata = new HashMap<>(); - metadata.put("requestId", HttpUtility.getRequestID()); + metadata.put(Constants.JsonFieldNames.REQUEST_ID, HttpUtility.getRequestID()); connectionResponse = new InvokeConnectionResponse(data, metadata, null); LogUtil.printInfoLog(InfoLogs.INVOKE_CONNECTION_REQUEST_RESOLVED.getLog()); } catch (IOException e) { @@ -84,7 +84,7 @@ private JsonObject convertObjectToJson(Object object) { return jsonElement.getAsJsonObject(); } else { JsonObject wrapper = new JsonObject(); - wrapper.add("value", jsonElement); + wrapper.add(Constants.JsonFieldNames.VALUE, jsonElement); return wrapper; } } diff --git a/src/main/java/com/skyflow/vault/controller/DetectController.java b/src/main/java/com/skyflow/vault/controller/DetectController.java index 5801d688..7a67c6dd 100644 --- a/src/main/java/com/skyflow/vault/controller/DetectController.java +++ b/src/main/java/com/skyflow/vault/controller/DetectController.java @@ -161,7 +161,7 @@ public DeidentifyFileResponse deidentifyFile(DeidentifyFileRequest request) thro String outputDir = request.getOutputDirectory(); if (entityBase64 != null) { byte[] entityDecodedBytes = Base64.getDecoder().decode(entityBase64); - String entityFileName = Constants.PROCESSED_FILE_NAME_PREFIX + fileName.substring(0, fileName.lastIndexOf('.')) + ".json"; + String entityFileName = Constants.PROCESSED_FILE_NAME_PREFIX + fileName.substring(0, fileName.lastIndexOf('.')) + Constants.FileExtension.JSON; File entityFile; if (outputDir != null && !outputDir.isEmpty()) { entityFile = new File(outputDir, entityFileName); @@ -284,7 +284,7 @@ private static synchronized DeidentifyFileResponse parseDeidentifyFileResponse(D byte[] decodedBytes = Base64.getDecoder().decode(processedFileBase64.get()); String suffix = "." + processedFileExtension.get(); String fileName = Constants.DEIDENTIFIED_FILE_PREFIX + suffix; - processedFileObject = new File(System.getProperty("java.io.tmpdir"), fileName); + processedFileObject = new File(System.getProperty(Constants.SystemProperty.JAVA_TEMP_DIR), fileName); Files.write(processedFileObject.toPath(), decodedBytes); fileInfo = new FileInfo(processedFileObject); processedFileObject.deleteOnExit(); @@ -350,54 +350,54 @@ private String extractBodyAsString(ApiClientApiException e) { private com.skyflow.generated.rest.types.DeidentifyFileResponse processFileByType(String fileExtension, String base64Content, DeidentifyFileRequest request, String vaultId) throws SkyflowException { switch (fileExtension.toLowerCase()) { - case "txt": + case Constants.FileFormatType.TXT: com.skyflow.generated.rest.resources.files.requests.DeidentifyFileRequestDeidentifyText textFileRequest = super.getDeidentifyTextFileRequest(request, vaultId, base64Content); return super.getDetectFileAPi().deidentifyText(textFileRequest); - case "mp3": - case "wav": + case Constants.FileFormatType.MP3: + case Constants.FileFormatType.WAV: DeidentifyFileAudioRequestDeidentifyAudio audioRequest = super.getDeidentifyAudioRequest(request, vaultId, base64Content, fileExtension); return super.getDetectFileAPi().deidentifyAudio(audioRequest); - case "pdf": + case Constants.FileFormatType.PDF: DeidentifyFileDocumentPdfRequestDeidentifyPdf pdfRequest = super.getDeidentifyPdfRequest(request, vaultId, base64Content); return super.getDetectFileAPi().deidentifyPdf(pdfRequest); - case "jpg": - case "jpeg": - case "png": - case "bmp": - case "tif": - case "tiff": + case Constants.FileFormatType.JPG: + case Constants.FileFormatType.JPEG: + case Constants.FileFormatType.PNG: + case Constants.FileFormatType.BMP: + case Constants.FileFormatType.TIF: + case Constants.FileFormatType.TIFF: DeidentifyFileImageRequestDeidentifyImage imageRequest = super.getDeidentifyImageRequest(request, vaultId, base64Content, fileExtension); return super.getDetectFileAPi().deidentifyImage(imageRequest); - case "ppt": - case "pptx": + case Constants.FileFormatType.PPT: + case Constants.FileFormatType.PPTX: DeidentifyFileRequestDeidentifyPresentation presentationRequest = super.getDeidentifyPresentationRequest(request, vaultId, base64Content, fileExtension); return super.getDetectFileAPi().deidentifyPresentation(presentationRequest); - case "csv": - case "xls": - case "xlsx": + case Constants.FileFormatType.CSV: + case Constants.FileFormatType.XLS: + case Constants.FileFormatType.XLSX: DeidentifyFileRequestDeidentifySpreadsheet spreadsheetRequest = super.getDeidentifySpreadsheetRequest(request, vaultId, base64Content, fileExtension); return super.getDetectFileAPi().deidentifySpreadsheet(spreadsheetRequest); - case "doc": - case "docx": + case Constants.FileFormatType.DOC: + case Constants.FileFormatType.DOCX: DeidentifyFileRequestDeidentifyDocument documentRequest = super.getDeidentifyDocumentRequest(request, vaultId, base64Content, fileExtension); return super.getDetectFileAPi().deidentifyDocument(documentRequest); - case "json": - case "xml": + case Constants.FileFormatType.JSON: + case Constants.FileFormatType.XML: DeidentifyFileRequestDeidentifyStructuredText structuredTextRequest = super.getDeidentifyStructuredTextRequest(request, vaultId, base64Content, fileExtension); return super.getDetectFileAPi().deidentifyStructuredText(structuredTextRequest); diff --git a/src/main/java/com/skyflow/vault/controller/VaultController.java b/src/main/java/com/skyflow/vault/controller/VaultController.java index 3a237470..1bb618ba 100644 --- a/src/main/java/com/skyflow/vault/controller/VaultController.java +++ b/src/main/java/com/skyflow/vault/controller/VaultController.java @@ -41,15 +41,15 @@ public VaultController(VaultConfig vaultConfig, Credentials credentials) { private static synchronized HashMap getFormattedBatchInsertRecord(Object record, Integer requestIndex) { HashMap insertRecord = new HashMap<>(); String jsonString = GSON.toJson(record); - JsonObject bodyObject = JsonParser.parseString(jsonString).getAsJsonObject().get("Body").getAsJsonObject(); - JsonArray records = bodyObject.getAsJsonArray("records"); - JsonPrimitive error = bodyObject.getAsJsonPrimitive("error"); + JsonObject bodyObject = JsonParser.parseString(jsonString).getAsJsonObject().get(Constants.JsonFieldNames.BODY).getAsJsonObject(); + JsonArray records = bodyObject.getAsJsonArray(Constants.JsonFieldNames.RECORDS); + JsonPrimitive error = bodyObject.getAsJsonPrimitive(Constants.JsonFieldNames.ERROR); if (records != null) { for (JsonElement recordElement : records) { JsonObject recordObject = recordElement.getAsJsonObject(); - insertRecord.put("skyflowId", recordObject.get("skyflow_id").getAsString()); - JsonElement tokensElement = recordObject.get("tokens"); + insertRecord.put(Constants.FieldNames.SKYFLOW_ID_CAMEL, recordObject.get(Constants.JsonFieldNames.SKYFLOW_ID).getAsString()); + JsonElement tokensElement = recordObject.get(Constants.JsonFieldNames.TOKENS); if (tokensElement != null) { insertRecord.putAll(tokensElement.getAsJsonObject().asMap()); } @@ -57,16 +57,16 @@ private static synchronized HashMap getFormattedBatchInsertRecor } if (error != null) { - insertRecord.put("error", error.getAsString()); + insertRecord.put(Constants.JsonFieldNames.ERROR, error.getAsString()); } - insertRecord.put("requestIndex", requestIndex); + insertRecord.put(Constants.JsonFieldNames.REQUEST_INDEX, requestIndex); return insertRecord; } private static synchronized HashMap getFormattedBulkInsertRecord(V1RecordMetaProperties record) { HashMap insertRecord = new HashMap<>(); if (record.getSkyflowId().isPresent()) { - insertRecord.put("skyflowId", record.getSkyflowId().get()); + insertRecord.put(Constants.FieldNames.SKYFLOW_ID_CAMEL, record.getSkyflowId().get()); } if (record.getTokens().isPresent()) { @@ -93,7 +93,7 @@ private static synchronized HashMap getFormattedGetRecord(V1Fiel private static synchronized HashMap getFormattedUpdateRecord(V1UpdateRecordResponse record) { HashMap updateTokens = new HashMap<>(); - record.getSkyflowId().ifPresent(skyflowId -> updateTokens.put("skyflowId", skyflowId)); + record.getSkyflowId().ifPresent(skyflowId -> updateTokens.put(Constants.FieldNames.SKYFLOW_ID_CAMEL, skyflowId)); record.getTokens().ifPresent(tokensMap -> updateTokens.putAll(tokensMap)); @@ -134,11 +134,11 @@ public InsertResponse insert(InsertRequest insertRequest) throws SkyflowExceptio Map record = recordList.get(index); HashMap insertRecord = getFormattedBatchInsertRecord(record, index); - if (insertRecord.containsKey("skyflowId")) { + if (insertRecord.containsKey(Constants.FieldNames.SKYFLOW_ID_CAMEL)) { insertedFields.add(insertRecord); } else { - insertRecord.put("requestId", batchInsertResult.headers().get(Constants.REQUEST_ID_HEADER_KEY).get(0)); - insertRecord.put("httpCode", ErrorCode.INVALID_INPUT.getCode()); + insertRecord.put(Constants.JsonFieldNames.REQUEST_ID, batchInsertResult.headers().get(Constants.REQUEST_ID_HEADER_KEY).get(0)); + insertRecord.put(Constants.JsonFieldNames.HTTP_CODE, ErrorCode.INVALID_INPUT.getCode()); errorFields.add(insertRecord); } } @@ -281,7 +281,7 @@ public UpdateResponse update(UpdateRequest updateRequest) throws SkyflowExceptio result = super.getRecordsApi().recordServiceUpdateRecord( super.getVaultConfig().getVaultId(), updateRequest.getTable(), - updateRequest.getData().remove("skyflow_id").toString(), + updateRequest.getData().remove(Constants.JsonFieldNames.SKYFLOW_ID).toString(), updateBody, requestOptions ); diff --git a/src/main/java/com/skyflow/vault/data/DeleteResponse.java b/src/main/java/com/skyflow/vault/data/DeleteResponse.java index f34d219a..0f243aa4 100644 --- a/src/main/java/com/skyflow/vault/data/DeleteResponse.java +++ b/src/main/java/com/skyflow/vault/data/DeleteResponse.java @@ -1,6 +1,7 @@ package com.skyflow.vault.data; import com.google.gson.Gson; +import com.skyflow.utils.Constants; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -21,7 +22,7 @@ public List getDeletedIds() { public String toString() { Gson gson = new Gson(); JsonObject responseObject = JsonParser.parseString(gson.toJson(this)).getAsJsonObject(); - responseObject.add("errors", null); + responseObject.add(Constants.JsonFieldNames.ERRORS, null); return responseObject.toString(); } } diff --git a/src/main/java/com/skyflow/vault/data/QueryResponse.java b/src/main/java/com/skyflow/vault/data/QueryResponse.java index 7a1bca51..5a9b735c 100644 --- a/src/main/java/com/skyflow/vault/data/QueryResponse.java +++ b/src/main/java/com/skyflow/vault/data/QueryResponse.java @@ -1,6 +1,7 @@ package com.skyflow.vault.data; import com.google.gson.*; +import com.skyflow.utils.Constants; import java.util.ArrayList; import java.util.HashMap; @@ -21,12 +22,12 @@ public ArrayList> getFields() { public String toString() { Gson gson = new GsonBuilder().serializeNulls().create(); JsonObject responseObject = gson.toJsonTree(this).getAsJsonObject(); - JsonArray fieldsArray = responseObject.get("fields").getAsJsonArray(); + JsonArray fieldsArray = responseObject.get(Constants.JsonFieldNames.FIELDS).getAsJsonArray(); for (JsonElement fieldElement : fieldsArray) { - fieldElement.getAsJsonObject().add("tokenizedData", new JsonObject()); + fieldElement.getAsJsonObject().add(Constants.FieldNames.TOKENIZED_DATA, new JsonObject()); } - responseObject.add("errors", null); - responseObject.remove("tokenizedData"); + responseObject.add(Constants.JsonFieldNames.ERRORS, null); + responseObject.remove(Constants.FieldNames.TOKENIZED_DATA); return responseObject.toString(); } } diff --git a/src/main/java/com/skyflow/vault/data/UpdateResponse.java b/src/main/java/com/skyflow/vault/data/UpdateResponse.java index 068b29be..0120edaa 100644 --- a/src/main/java/com/skyflow/vault/data/UpdateResponse.java +++ b/src/main/java/com/skyflow/vault/data/UpdateResponse.java @@ -1,6 +1,7 @@ package com.skyflow.vault.data; import com.google.gson.Gson; +import com.skyflow.utils.Constants; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -28,13 +29,13 @@ public HashMap getTokens() { public String toString() { Gson gson = new Gson(); JsonObject responseObject = JsonParser.parseString(gson.toJson(this)).getAsJsonObject(); - JsonObject tokensObject = responseObject.remove("tokens").getAsJsonObject(); + JsonObject tokensObject = responseObject.remove(Constants.JsonFieldNames.TOKENS).getAsJsonObject(); for (String key : tokensObject.keySet()) { responseObject.add(key, tokensObject.get(key)); } JsonObject finalResponseObject = new JsonObject(); - finalResponseObject.add("updatedField", responseObject); - finalResponseObject.add("errors", null); + finalResponseObject.add(Constants.JsonFieldNames.UPDATED_FIELD, responseObject); + finalResponseObject.add(Constants.JsonFieldNames.ERRORS, null); return finalResponseObject.toString(); } } diff --git a/src/main/java/com/skyflow/vault/tokens/DetokenizeResponse.java b/src/main/java/com/skyflow/vault/tokens/DetokenizeResponse.java index bd1d7cde..d00fc8d2 100644 --- a/src/main/java/com/skyflow/vault/tokens/DetokenizeResponse.java +++ b/src/main/java/com/skyflow/vault/tokens/DetokenizeResponse.java @@ -1,6 +1,7 @@ package com.skyflow.vault.tokens; import com.google.gson.ExclusionStrategy; +import com.skyflow.utils.Constants; import com.google.gson.FieldAttributes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -32,18 +33,18 @@ public String toString() { DetokenizeRecordResponse.class, (com.google.gson.JsonSerializer) (src, typeOfSrc, context) -> { com.google.gson.JsonObject obj = new com.google.gson.JsonObject(); - obj.addProperty("token", src.getToken()); + obj.addProperty(Constants.ApiToken.TOKEN, src.getToken()); if (src.getValue() != null) { - obj.addProperty("value", src.getValue()); + obj.addProperty(Constants.JsonFieldNames.VALUE, src.getValue()); } if (src.getType() != null) { - obj.addProperty("type", src.getType()); + obj.addProperty(Constants.JsonFieldNames.TYPE, src.getType()); } if (src.getError() != null) { - obj.add("error", context.serialize(src.getError())); + obj.add(Constants.JsonFieldNames.ERROR, context.serialize(src.getError())); } if (src.getRequestId() != null) { - obj.addProperty("requestId", src.getRequestId()); + obj.addProperty(Constants.JsonFieldNames.REQUEST_ID, src.getRequestId()); } return obj; } diff --git a/src/main/java/com/skyflow/vault/tokens/TokenizeResponse.java b/src/main/java/com/skyflow/vault/tokens/TokenizeResponse.java index d8d8072b..29b5e2bb 100644 --- a/src/main/java/com/skyflow/vault/tokens/TokenizeResponse.java +++ b/src/main/java/com/skyflow/vault/tokens/TokenizeResponse.java @@ -1,6 +1,7 @@ package com.skyflow.vault.tokens; import com.google.gson.*; +import com.skyflow.utils.Constants; import java.util.List; @@ -19,15 +20,15 @@ public List getTokens() { public String toString() { Gson gson = new Gson(); JsonObject responseObject = JsonParser.parseString(gson.toJson(this)).getAsJsonObject(); - JsonArray tokensArray = responseObject.remove("tokens").getAsJsonArray(); + JsonArray tokensArray = responseObject.remove(Constants.JsonFieldNames.TOKENS).getAsJsonArray(); JsonArray newTokensArray = new JsonArray(); for (JsonElement token : tokensArray) { JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("token", token.getAsString()); + jsonObject.addProperty(Constants.ApiToken.TOKEN, token.getAsString()); newTokensArray.add(jsonObject); } - responseObject.add("tokens", newTokensArray); - responseObject.add("errors", null); + responseObject.add(Constants.JsonFieldNames.TOKENS, newTokensArray); + responseObject.add(Constants.JsonFieldNames.ERRORS, null); return responseObject.toString(); } } From 84cb6dfdfe5564d62605ef15666c83a8aafd889c Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Mon, 2 Feb 2026 15:12:36 +0530 Subject: [PATCH 02/10] aadarsh-st/SK-2521-Enhance content-type handling and add validation tests for request bodies --- src/main/java/com/skyflow/logs/InfoLogs.java | 2 +- .../java/com/skyflow/utils/HttpUtility.java | 23 ++- src/main/java/com/skyflow/utils/Utils.java | 17 ++- .../utils/validations/Validations.java | 28 +++- .../controller/ConnectionController.java | 46 ++++-- .../com/skyflow/utils/HttpUtilityTests.java | 67 +++++++++ .../connection/InvokeConnectionTests.java | 141 ++++++++++++++++++ .../controller/ConnectionControllerTests.java | 89 +++++++++++ 8 files changed, 391 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/skyflow/logs/InfoLogs.java b/src/main/java/com/skyflow/logs/InfoLogs.java index f71fc416..18363670 100644 --- a/src/main/java/com/skyflow/logs/InfoLogs.java +++ b/src/main/java/com/skyflow/logs/InfoLogs.java @@ -14,7 +14,7 @@ public enum InfoLogs { // Bearer token generation EMPTY_BEARER_TOKEN("Bearer token is empty."), - BEARER_TOKEN_EXPIRED("Bearer token is expired."), + BEARER_TOKEN_EXPIRED("Bearer token is invalid or expired."), GET_BEARER_TOKEN_TRIGGERED("getBearerToken method triggered."), GET_BEARER_TOKEN_SUCCESS("Bearer token generated."), GET_SIGNED_DATA_TOKENS_TRIGGERED("getSignedDataTokens method triggered."), diff --git a/src/main/java/com/skyflow/utils/HttpUtility.java b/src/main/java/com/skyflow/utils/HttpUtility.java index b8e9283b..93269993 100644 --- a/src/main/java/com/skyflow/utils/HttpUtility.java +++ b/src/main/java/com/skyflow/utils/HttpUtility.java @@ -7,6 +7,7 @@ import java.io.*; import java.net.HttpURLConnection; import java.net.URL; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; @@ -32,9 +33,14 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< try { connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod(method); - connection.setRequestProperty("content-type", "application/json"); connection.setRequestProperty("Accept", "*/*"); + // Set default content-type if not provided in headers + boolean hasContentType = headers != null && headers.containsKey("content-type"); + if (!hasContentType && params != null && !params.isEmpty()) { + connection.setRequestProperty("content-type", "application/json"); + } + if (headers != null && !headers.isEmpty()) { for (Map.Entry entry : headers.entrySet()) connection.setRequestProperty(entry.getKey(), entry.getValue()); @@ -52,9 +58,12 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< byte[] input = null; String requestContentType = connection.getRequestProperty("content-type"); - if (requestContentType.contains("application/x-www-form-urlencoded")) { + // Check if this is a raw body (XML, plain text, etc.) + if (params.has("__raw_body__") && params.size() == 1) { + input = params.get("__raw_body__").getAsString().getBytes(StandardCharsets.UTF_8); + } else if (requestContentType != null && requestContentType.contains("application/x-www-form-urlencoded")) { input = formatJsonToFormEncodedString(params).getBytes(StandardCharsets.UTF_8); - } else if (requestContentType.contains("multipart/form-data")) { + } else if (requestContentType != null && requestContentType.contains("multipart/form-data")) { input = formatJsonToMultiPartFormDataString(params, boundary).getBytes(StandardCharsets.UTF_8); } else { input = params.toString().getBytes(StandardCharsets.UTF_8); @@ -159,7 +168,13 @@ public static String appendRequestId(String message, String requestId) { } private static String makeFormEncodeKeyValuePair(String key, String value) { - return key + "=" + value + "&"; + try { + String encodedKey = URLEncoder.encode(key, StandardCharsets.UTF_8.toString()); + String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); + return encodedKey + "=" + encodedValue + "&"; + } catch (Exception e) { + return key + "=" + value + "&"; + } } } diff --git a/src/main/java/com/skyflow/utils/Utils.java b/src/main/java/com/skyflow/utils/Utils.java index 165c6a80..d6456466 100644 --- a/src/main/java/com/skyflow/utils/Utils.java +++ b/src/main/java/com/skyflow/utils/Utils.java @@ -17,6 +17,8 @@ import java.io.File; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; @@ -110,7 +112,12 @@ public static String constructConnectionURL(ConnectionConfig config, InvokeConne for (Map.Entry entry : invokeConnectionRequest.getPathParams().entrySet()) { String key = entry.getKey(); String value = entry.getValue(); - filledURL = new StringBuilder(filledURL.toString().replace(String.format("{%s}", key), value)); + try { + String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); + filledURL = new StringBuilder(filledURL.toString().replace(String.format("{%s}", key), encodedValue)); + } catch (Exception e) { + filledURL = new StringBuilder(filledURL.toString().replace(String.format("{%s}", key), value)); + } } } @@ -119,7 +126,13 @@ public static String constructConnectionURL(ConnectionConfig config, InvokeConne for (Map.Entry entry : invokeConnectionRequest.getQueryParams().entrySet()) { String key = entry.getKey(); String value = entry.getValue(); - filledURL.append(key).append("=").append(value).append("&"); + try { + String encodedKey = URLEncoder.encode(key, StandardCharsets.UTF_8.toString()); + String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); + filledURL.append(encodedKey).append("=").append(encodedValue).append("&"); + } catch (Exception e) { + filledURL.append(key).append("=").append(value).append("&"); + } } filledURL = new StringBuilder(filledURL.substring(0, filledURL.length() - 1)); } diff --git a/src/main/java/com/skyflow/utils/validations/Validations.java b/src/main/java/com/skyflow/utils/validations/Validations.java index 0372749a..4c403b3b 100644 --- a/src/main/java/com/skyflow/utils/validations/Validations.java +++ b/src/main/java/com/skyflow/utils/validations/Validations.java @@ -1,6 +1,7 @@ package com.skyflow.utils.validations; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.skyflow.config.ConnectionConfig; import com.skyflow.config.Credentials; @@ -137,12 +138,27 @@ public static void validateInvokeConnectionRequest(InvokeConnectionRequest invok } if (requestBody != null) { - Gson gson = new Gson(); - JsonObject bodyObject = gson.toJsonTree(requestBody).getAsJsonObject(); - if (bodyObject.isEmpty()) { - LogUtil.printErrorLog(Utils.parameterizedString( - ErrorLogs.EMPTY_REQUEST_BODY.getLog(), InterfaceName.INVOKE_CONNECTION.getName())); - throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyRequestBody.getMessage()); + if (requestBody.getClass().equals(Object.class)) { + return; + } + if (requestBody instanceof String) { + String bodyStr = (String) requestBody; + if (bodyStr.trim().isEmpty()) { + LogUtil.printErrorLog(Utils.parameterizedString( + ErrorLogs.EMPTY_REQUEST_BODY.getLog(), InterfaceName.INVOKE_CONNECTION.getName())); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyRequestBody.getMessage()); + } + } else { + Gson gson = new Gson(); + JsonElement bodyElement = gson.toJsonTree(requestBody); + if (bodyElement.isJsonObject()) { + JsonObject bodyObject = bodyElement.getAsJsonObject(); + if (bodyObject.isEmpty()) { + LogUtil.printErrorLog(Utils.parameterizedString( + ErrorLogs.EMPTY_REQUEST_BODY.getLog(), InterfaceName.INVOKE_CONNECTION.getName())); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyRequestBody.getMessage()); + } + } } } } diff --git a/src/main/java/com/skyflow/vault/controller/ConnectionController.java b/src/main/java/com/skyflow/vault/controller/ConnectionController.java index 4a9334d4..3734aceb 100644 --- a/src/main/java/com/skyflow/vault/controller/ConnectionController.java +++ b/src/main/java/com/skyflow/vault/controller/ConnectionController.java @@ -51,20 +51,48 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR headers.put(Constants.SDK_METRICS_HEADER_KEY, Utils.getMetrics().toString()); RequestMethod requestMethod = invokeConnectionRequest.getMethod(); - JsonObject requestBody = null; Object requestBodyObject = invokeConnectionRequest.getRequestBody(); + String contentType = headers + .getOrDefault("content-type", "application/json") + .toLowerCase(); + boolean isJsonRequest = contentType.contains("application/json"); - if (requestBodyObject != null) { - try { - requestBody = convertObjectToJson(requestBodyObject); - } catch (Exception e) { - LogUtil.printErrorLog(ErrorLogs.INVALID_REQUEST_HEADERS.getLog()); - throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidRequestBody.getMessage()); + Object finalPayload; + + try { + if (requestBodyObject instanceof String) { + if (isJsonRequest) { + JsonObject jsonWrapper = new JsonObject(); + jsonWrapper.addProperty( + "__raw_body__", + (String) requestBodyObject + ); + finalPayload = jsonWrapper; + } else { + finalPayload = requestBodyObject; + } + } else if (requestBodyObject instanceof JsonObject || requestBodyObject == null) { + finalPayload = requestBodyObject; + } else { + finalPayload = convertObjectToJson(requestBodyObject); } + } catch (Exception e) { + LogUtil.printErrorLog(ErrorLogs.INVALID_REQUEST_HEADERS.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidRequestBody.getMessage()); + } + JsonObject payloadToSend; + if (finalPayload instanceof JsonObject || finalPayload == null) { + payloadToSend = (JsonObject) finalPayload; + } else { + payloadToSend = new JsonObject(); + payloadToSend.addProperty("__raw_body__", finalPayload.toString()); } - String response = HttpUtility.sendRequest(requestMethod.name(), new URL(filledURL), requestBody, headers); - JsonObject data = JsonParser.parseString(response).getAsJsonObject(); + String response = HttpUtility.sendRequest(requestMethod.name(), new URL(filledURL), payloadToSend, headers); + Object data = response; + try { + data = JsonParser.parseString(response).getAsJsonObject(); + } catch (Exception ignored) {} HashMap metadata = new HashMap<>(); metadata.put("requestId", HttpUtility.getRequestID()); connectionResponse = new InvokeConnectionResponse(data, metadata, null); diff --git a/src/test/java/com/skyflow/utils/HttpUtilityTests.java b/src/test/java/com/skyflow/utils/HttpUtilityTests.java index f7214690..5f7271e1 100644 --- a/src/test/java/com/skyflow/utils/HttpUtilityTests.java +++ b/src/test/java/com/skyflow/utils/HttpUtilityTests.java @@ -124,4 +124,71 @@ public void testSendRequestError() { fail(INVALID_EXCEPTION_THROWN); } } + + // New test cases for content-type handling changes + + @Test + @PrepareForTest({URL.class, HttpURLConnection.class}) + public void testSendRequestWithRawBody() { + try { + given(mockConnection.getRequestProperty("content-type")).willReturn("application/xml"); + Map headers = new HashMap<>(); + headers.put("content-type", "application/xml"); + JsonObject params = new JsonObject(); + params.addProperty("__raw_body__", "test"); + String response = httpUtility.sendRequest("POST", url, params, headers); + Assert.assertEquals(expected, response); + } catch (Exception e) { + fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + @PrepareForTest({URL.class, HttpURLConnection.class}) + public void testSendRequestWithoutContentTypeHeader() { + try { + given(mockConnection.getRequestProperty("content-type")).willReturn("application/json"); + JsonObject params = new JsonObject(); + params.addProperty("key", "value"); + String response = httpUtility.sendRequest("POST", url, params, null); + Assert.assertEquals(expected, response); + } catch (Exception e) { + fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + @PrepareForTest({URL.class, HttpURLConnection.class}) + public void testSendRequestWithNullRequestId() { + try { + given(mockConnection.getHeaderField(anyString())).willReturn(null); + given(mockConnection.getRequestProperty("content-type")).willReturn("application/json"); + Map headers = new HashMap<>(); + headers.put("content-type", "application/json"); + JsonObject params = new JsonObject(); + params.addProperty("key", "value"); + String response = httpUtility.sendRequest("GET", url, params, headers); + Assert.assertEquals(expected, response); + Assert.assertNotNull(HttpUtility.getRequestID()); + } catch (Exception e) { + fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + @PrepareForTest({URL.class, HttpURLConnection.class}) + public void testSendRequestFormURLEncodedWithSpecialCharacters() { + try { + given(mockConnection.getRequestProperty("content-type")).willReturn("application/x-www-form-urlencoded"); + Map headers = new HashMap<>(); + headers.put("content-type", "application/x-www-form-urlencoded"); + JsonObject params = new JsonObject(); + params.addProperty("key", "value with spaces"); + params.addProperty("special", "test@email.com"); + String response = httpUtility.sendRequest("POST", url, params, headers); + Assert.assertEquals(expected, response); + } catch (Exception e) { + fail(INVALID_EXCEPTION_THROWN); + } + } } diff --git a/src/test/java/com/skyflow/vault/connection/InvokeConnectionTests.java b/src/test/java/com/skyflow/vault/connection/InvokeConnectionTests.java index 63717b5c..e87d7877 100644 --- a/src/test/java/com/skyflow/vault/connection/InvokeConnectionTests.java +++ b/src/test/java/com/skyflow/vault/connection/InvokeConnectionTests.java @@ -437,4 +437,145 @@ public void testInvokeConnectionResponse() { Assert.fail(INVALID_EXCEPTION_THROWN); } } + + // New test cases for content-type handling changes + + @Test + public void testValidStringRequestBodyInInvokeConnectionRequestValidations() { + try { + String xmlBody = "test"; + requestHeaders.put("Content-Type", "application/xml"); + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestHeaders(requestHeaders) + .requestBody(xmlBody) + .build(); + Validations.validateInvokeConnectionRequest(request); + Assert.assertTrue(request.getRequestBody() instanceof String); + Assert.assertEquals(xmlBody, request.getRequestBody()); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testEmptyStringRequestBodyInInvokeConnectionRequestValidations() { + try { + String emptyBody = ""; + requestHeaders.put("Content-Type", "application/xml"); + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestHeaders(requestHeaders) + .requestBody(emptyBody) + .build(); + Validations.validateInvokeConnectionRequest(request); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.EmptyRequestBody.getMessage(), e.getMessage()); + } + } + + @Test + public void testWhitespaceOnlyStringRequestBodyInInvokeConnectionRequestValidations() { + try { + String whitespaceBody = " \n\t "; + requestHeaders.put("Content-Type", "application/xml"); + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestHeaders(requestHeaders) + .requestBody(whitespaceBody) + .build(); + Validations.validateInvokeConnectionRequest(request); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.EmptyRequestBody.getMessage(), e.getMessage()); + } + } + + @Test + public void testXMLStringRequestBodyInInvokeConnectionRequestValidations() { + try { + String xmlBody = "4111111111111111"; + requestHeaders.put("Content-Type", "application/xml"); + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestHeaders(requestHeaders) + .requestBody(xmlBody) + .build(); + Validations.validateInvokeConnectionRequest(request); + Assert.assertTrue(request.getRequestBody() instanceof String); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testPlainTextRequestBodyInInvokeConnectionRequestValidations() { + try { + String plainText = "This is a plain text request body with some data"; + requestHeaders.put("Content-Type", "text/plain"); + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestHeaders(requestHeaders) + .requestBody(plainText) + .build(); + Validations.validateInvokeConnectionRequest(request); + Assert.assertTrue(request.getRequestBody() instanceof String); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testHTMLRequestBodyInInvokeConnectionRequestValidations() { + try { + String htmlBody = "

Processing Payment

"; + requestHeaders.put("Content-Type", "text/html"); + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestHeaders(requestHeaders) + .requestBody(htmlBody) + .build(); + Validations.validateInvokeConnectionRequest(request); + Assert.assertTrue(request.getRequestBody() instanceof String); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testInvokeConnectionResponseWithStringData() { + try { + String xmlData = "success"; + HashMap metadata = new HashMap<>(); + metadata.put("requestId", "xml-12345"); + InvokeConnectionResponse connectionResponse = new InvokeConnectionResponse(xmlData, metadata, null); + + Assert.assertNotNull(connectionResponse.getData()); + Assert.assertTrue(connectionResponse.getData() instanceof String); + Assert.assertEquals(xmlData, connectionResponse.getData()); + Assert.assertEquals("xml-12345", connectionResponse.getMetadata().get("requestId")); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testRequestBodyWithSpecialCharacters() { + try { + String bodyWithSpecialChars = "card_number=4111111111111111&exp_month=12&exp_year=2025&cvv=123"; + requestHeaders.put("Content-Type", "application/x-www-form-urlencoded"); + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestHeaders(requestHeaders) + .requestBody(bodyWithSpecialChars) + .build(); + Validations.validateInvokeConnectionRequest(request); + Assert.assertTrue(request.getRequestBody() instanceof String); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } } diff --git a/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java b/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java index b121280a..750b0ebe 100644 --- a/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java +++ b/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java @@ -49,4 +49,93 @@ public void testInvalidRequestInInvokeConnectionMethod() { Assert.assertEquals(ErrorMessage.EmptyRequestBody.getMessage(), e.getMessage()); } } + + // New test cases for content-type handling changes + + @Test + public void testInvokeConnectionWithStringRequestBody() { + try { + String xmlBody = "test"; + HashMap headers = new HashMap<>(); + headers.put("Content-Type", "application/xml"); + InvokeConnectionRequest connectionRequest = InvokeConnectionRequest.builder() + .requestBody(xmlBody) + .requestHeaders(headers) + .build(); + Assert.assertNotNull(connectionRequest.getRequestBody()); + Assert.assertTrue(connectionRequest.getRequestBody() instanceof String); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testInvokeConnectionWithEmptyStringRequestBody() { + try { + String emptyBody = ""; + HashMap headers = new HashMap<>(); + headers.put("Content-Type", "application/xml"); + InvokeConnectionRequest connectionRequest = InvokeConnectionRequest.builder() + .requestBody(emptyBody) + .requestHeaders(headers) + .build(); + Skyflow skyflowClient = Skyflow.builder().setLogLevel(LogLevel.DEBUG).addConnectionConfig(connectionConfig).build(); + skyflowClient.connection().invoke(connectionRequest); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.EmptyRequestBody.getMessage(), e.getMessage()); + } + } + + @Test + public void testInvokeConnectionWithXMLContentType() { + try { + String xmlBody = "4111111111111111"; + HashMap headers = new HashMap<>(); + headers.put("Content-Type", "application/xml"); + InvokeConnectionRequest connectionRequest = InvokeConnectionRequest.builder() + .requestBody(xmlBody) + .requestHeaders(headers) + .build(); + Assert.assertEquals("application/xml", connectionRequest.getRequestHeaders().get("Content-Type")); + Assert.assertTrue(connectionRequest.getRequestBody() instanceof String); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testInvokeConnectionWithPlainTextContentType() { + try { + String plainTextBody = "This is a plain text request body"; + HashMap headers = new HashMap<>(); + headers.put("Content-Type", "text/plain"); + InvokeConnectionRequest connectionRequest = InvokeConnectionRequest.builder() + .requestBody(plainTextBody) + .requestHeaders(headers) + .build(); + Assert.assertEquals("text/plain", connectionRequest.getRequestHeaders().get("Content-Type")); + Assert.assertTrue(connectionRequest.getRequestBody() instanceof String); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testInvokeConnectionWithHTMLContentType() { + try { + String htmlBody = "

Test

"; + HashMap headers = new HashMap<>(); + headers.put("Content-Type", "text/html"); + InvokeConnectionRequest connectionRequest = InvokeConnectionRequest.builder() + .requestBody(htmlBody) + .requestHeaders(headers) + .build(); + Assert.assertEquals("text/html", connectionRequest.getRequestHeaders().get("Content-Type")); + Assert.assertTrue(connectionRequest.getRequestBody() instanceof String); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } } From 834b79ea33a186ff0a52f7f1e755342ea09dd1ab Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Mon, 2 Feb 2026 15:47:02 +0530 Subject: [PATCH 03/10] aadarsh-st/SK-2521:Fixed copilot comments --- src/main/java/com/skyflow/utils/HttpUtility.java | 8 ++++++-- src/main/java/com/skyflow/utils/Utils.java | 6 +++--- .../skyflow/vault/controller/ConnectionController.java | 4 +++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/skyflow/utils/HttpUtility.java b/src/main/java/com/skyflow/utils/HttpUtility.java index 93269993..4cb98338 100644 --- a/src/main/java/com/skyflow/utils/HttpUtility.java +++ b/src/main/java/com/skyflow/utils/HttpUtility.java @@ -76,14 +76,18 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< int httpCode = connection.getResponseCode(); String requestID = connection.getHeaderField("x-request-id"); - HttpUtility.requestID = requestID.split(",")[0]; + if (requestID != null) { + HttpUtility.requestID = requestID.split(",")[0]; + } else { + HttpUtility.requestID = "Internal-SDK-" + UUID.randomUUID(); + } Map> responseHeaders = connection.getHeaderFields(); Reader streamReader; if (httpCode > 299) { if (connection.getErrorStream() != null) streamReader = new InputStreamReader(connection.getErrorStream()); else { - String description = appendRequestId("replace with description", requestID); + String description = appendRequestId("Server returned error", requestID); throw new SkyflowException(description); } } else { diff --git a/src/main/java/com/skyflow/utils/Utils.java b/src/main/java/com/skyflow/utils/Utils.java index d6456466..75ffb7ce 100644 --- a/src/main/java/com/skyflow/utils/Utils.java +++ b/src/main/java/com/skyflow/utils/Utils.java @@ -113,7 +113,7 @@ public static String constructConnectionURL(ConnectionConfig config, InvokeConne String key = entry.getKey(); String value = entry.getValue(); try { - String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); + String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.name()); filledURL = new StringBuilder(filledURL.toString().replace(String.format("{%s}", key), encodedValue)); } catch (Exception e) { filledURL = new StringBuilder(filledURL.toString().replace(String.format("{%s}", key), value)); @@ -127,8 +127,8 @@ public static String constructConnectionURL(ConnectionConfig config, InvokeConne String key = entry.getKey(); String value = entry.getValue(); try { - String encodedKey = URLEncoder.encode(key, StandardCharsets.UTF_8.toString()); - String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); + String encodedKey = URLEncoder.encode(key, StandardCharsets.UTF_8.name()); + String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.name()); filledURL.append(encodedKey).append("=").append(encodedValue).append("&"); } catch (Exception e) { filledURL.append(key).append("=").append(value).append("&"); diff --git a/src/main/java/com/skyflow/vault/controller/ConnectionController.java b/src/main/java/com/skyflow/vault/controller/ConnectionController.java index 3734aceb..0eb260ab 100644 --- a/src/main/java/com/skyflow/vault/controller/ConnectionController.java +++ b/src/main/java/com/skyflow/vault/controller/ConnectionController.java @@ -92,7 +92,9 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR Object data = response; try { data = JsonParser.parseString(response).getAsJsonObject(); - } catch (Exception ignored) {} + } catch (Exception e) { + LogUtil.printErrorLog(ErrorLogs.INVOKE_CONNECTION_REQUEST_REJECTED.getLog()); + } HashMap metadata = new HashMap<>(); metadata.put("requestId", HttpUtility.getRequestID()); connectionResponse = new InvokeConnectionResponse(data, metadata, null); From cdde0533ac75b73e9fd961b753532f62e87f906f Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Mon, 2 Feb 2026 16:07:31 +0530 Subject: [PATCH 04/10] aadarsh-st/SK-2521-Refactor request handling in ConnectionController and update request ID format in HttpUtility --- .../java/com/skyflow/utils/HttpUtility.java | 3 ++- .../controller/ConnectionController.java | 20 +++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/skyflow/utils/HttpUtility.java b/src/main/java/com/skyflow/utils/HttpUtility.java index 4cb98338..f0ce175c 100644 --- a/src/main/java/com/skyflow/utils/HttpUtility.java +++ b/src/main/java/com/skyflow/utils/HttpUtility.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.UUID; public final class HttpUtility { @@ -79,7 +80,7 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< if (requestID != null) { HttpUtility.requestID = requestID.split(",")[0]; } else { - HttpUtility.requestID = "Internal-SDK-" + UUID.randomUUID(); + HttpUtility.requestID = "SDK-Generated-" + UUID.randomUUID(); } Map> responseHeaders = connection.getHeaderFields(); Reader streamReader; diff --git a/src/main/java/com/skyflow/vault/controller/ConnectionController.java b/src/main/java/com/skyflow/vault/controller/ConnectionController.java index 0eb260ab..58a68230 100644 --- a/src/main/java/com/skyflow/vault/controller/ConnectionController.java +++ b/src/main/java/com/skyflow/vault/controller/ConnectionController.java @@ -52,12 +52,12 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR RequestMethod requestMethod = invokeConnectionRequest.getMethod(); Object requestBodyObject = invokeConnectionRequest.getRequestBody(); - String contentType = headers + String requestContentType = headers .getOrDefault("content-type", "application/json") .toLowerCase(); - boolean isJsonRequest = contentType.contains("application/json"); + boolean isJsonRequest = requestContentType.contains("application/json"); - Object finalPayload; + Object processedRequestBody; try { if (requestBodyObject instanceof String) { @@ -67,25 +67,25 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR "__raw_body__", (String) requestBodyObject ); - finalPayload = jsonWrapper; + processedRequestBody = jsonWrapper; } else { - finalPayload = requestBodyObject; + processedRequestBody = requestBodyObject; } } else if (requestBodyObject instanceof JsonObject || requestBodyObject == null) { - finalPayload = requestBodyObject; + processedRequestBody = requestBodyObject; } else { - finalPayload = convertObjectToJson(requestBodyObject); + processedRequestBody = convertObjectToJson(requestBodyObject); } } catch (Exception e) { LogUtil.printErrorLog(ErrorLogs.INVALID_REQUEST_HEADERS.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidRequestBody.getMessage()); } JsonObject payloadToSend; - if (finalPayload instanceof JsonObject || finalPayload == null) { - payloadToSend = (JsonObject) finalPayload; + if (processedRequestBody instanceof JsonObject || processedRequestBody == null) { + payloadToSend = (JsonObject) processedRequestBody; } else { payloadToSend = new JsonObject(); - payloadToSend.addProperty("__raw_body__", finalPayload.toString()); + payloadToSend.addProperty("__raw_body__", processedRequestBody.toString()); } String response = HttpUtility.sendRequest(requestMethod.name(), new URL(filledURL), payloadToSend, headers); From e31e5900efe496e9ae2cf0a9dac4d53ef474dd66 Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Mon, 2 Feb 2026 16:41:35 +0530 Subject: [PATCH 05/10] aadarsh-st/SK-2521-Fixed test cases and coverage --- .../controller/ConnectionControllerTests.java | 299 ++++++++++++++++++ 1 file changed, 299 insertions(+) diff --git a/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java b/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java index 750b0ebe..5c884dcf 100644 --- a/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java +++ b/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java @@ -1,19 +1,36 @@ package com.skyflow.vault.controller; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.skyflow.Skyflow; import com.skyflow.config.ConnectionConfig; import com.skyflow.config.Credentials; import com.skyflow.enums.LogLevel; +import com.skyflow.enums.RequestMethod; import com.skyflow.errors.ErrorCode; import com.skyflow.errors.ErrorMessage; import com.skyflow.errors.SkyflowException; +import com.skyflow.utils.HttpUtility; import com.skyflow.vault.connection.InvokeConnectionRequest; +import com.skyflow.vault.connection.InvokeConnectionResponse; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import java.net.URL; import java.util.HashMap; +import java.util.Map; +import static org.mockito.ArgumentMatchers.*; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({HttpUtility.class}) public class ConnectionControllerTests { private static final String INVALID_EXCEPTION_THROWN = "Should not have thrown any exception"; private static final String EXCEPTION_NOT_THROWN = "Should have thrown an exception"; @@ -36,6 +53,12 @@ public static void setup() { connectionConfig.setCredentials(credentials); } + @Before + public void setupMocks() throws Exception { + PowerMockito.mockStatic(HttpUtility.class); + when(HttpUtility.getRequestID()).thenReturn("test-request-id"); + } + @Test public void testInvalidRequestInInvokeConnectionMethod() { try { @@ -138,4 +161,280 @@ public void testInvokeConnectionWithHTMLContentType() { Assert.fail(INVALID_EXCEPTION_THROWN); } } + + // Tests for new content-type handling logic with actual controller invocation + + @Test + public void testInvokeConnectionWithStringBodyAndJsonContentType() throws Exception { + String jsonResponse = "{\"success\":true}"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(jsonResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + String stringBody = "{\"key\":\"value\"}"; + Map headers = new HashMap<>(); + headers.put("content-type", "application/json"); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(stringBody) + .requestHeaders(headers) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertTrue(response.getData() instanceof JsonObject); + } + + @Test + public void testInvokeConnectionWithStringBodyAndXmlContentType() throws Exception { + String xmlResponse = "success"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(xmlResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + String xmlBody = "test"; + Map headers = new HashMap<>(); + headers.put("content-type", "application/xml"); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(xmlBody) + .requestHeaders(headers) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + // When response is not valid JSON, it should be returned as String + Assert.assertTrue(response.getData() instanceof String); + Assert.assertEquals(xmlResponse, response.getData()); + } + + @Test + public void testInvokeConnectionWithJsonObjectBody() throws Exception { + String jsonResponse = "{\"result\":\"ok\"}"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(jsonResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + JsonObject jsonBody = new JsonObject(); + jsonBody.addProperty("test", "value"); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(jsonBody) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertTrue(response.getData() instanceof JsonObject); + } + + @Test + public void testInvokeConnectionWithNullRequestBody() throws Exception { + String jsonResponse = "{\"status\":\"success\"}"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(jsonResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.GET) + .requestBody(null) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertTrue(response.getData() instanceof JsonObject); + } + + @Test + public void testInvokeConnectionWithNonJsonResponse() throws Exception { + String plainTextResponse = "This is a plain text response"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(plainTextResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + JsonObject jsonBody = new JsonObject(); + jsonBody.addProperty("key", "value"); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(jsonBody) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + // Non-JSON response should be returned as String + Assert.assertTrue(response.getData() instanceof String); + Assert.assertEquals(plainTextResponse, response.getData()); + } + + @Test + public void testInvokeConnectionWithContentTypeCaseInsensitive() throws Exception { + String jsonResponse = "{\"data\":\"test\"}"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(jsonResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + String stringBody = "test data"; + Map headers = new HashMap<>(); + // Test with uppercase Content-Type + headers.put("Content-Type", "APPLICATION/JSON"); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(stringBody) + .requestHeaders(headers) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertTrue(response.getData() instanceof JsonObject); + } + + @Test + public void testInvokeConnectionWithMixedCaseContentType() throws Exception { + String xmlResponse = "data"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(xmlResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + String stringBody = "test"; + Map headers = new HashMap<>(); + headers.put("content-type", "Application/Xml"); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(stringBody) + .requestHeaders(headers) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertTrue(response.getData() instanceof String); + } + + @Test + public void testInvokeConnectionWithMapRequestBody() throws Exception { + String jsonResponse = "{\"created\":true}"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(jsonResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + Map mapBody = new HashMap<>(); + mapBody.put("name", "John"); + mapBody.put("age", "30"); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(mapBody) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertTrue(response.getData() instanceof JsonObject); + } + + @Test + public void testInvokeConnectionWithDefaultContentType() throws Exception { + String jsonResponse = "{\"message\":\"success\"}"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(jsonResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + String stringBody = "string data"; + // No content-type header - should default to application/json + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(stringBody) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertTrue(response.getData() instanceof JsonObject); + } + + @Test + public void testInvokeConnectionWithFormUrlEncodedContentType() throws Exception { + String jsonResponse = "{\"submitted\":true}"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(jsonResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + String formBody = "param1=value1¶m2=value2"; + Map headers = new HashMap<>(); + headers.put("content-type", "application/x-www-form-urlencoded"); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.POST) + .requestBody(formBody) + .requestHeaders(headers) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertTrue(response.getData() instanceof JsonObject); + } + + @Test + public void testInvokeConnectionMetadataContainsRequestId() throws Exception { + String jsonResponse = "{\"data\":\"value\"}"; + when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + .thenReturn(jsonResponse); + + Skyflow client = Skyflow.builder() + .setLogLevel(LogLevel.DEBUG) + .addConnectionConfig(connectionConfig) + .build(); + + InvokeConnectionRequest request = InvokeConnectionRequest.builder() + .method(RequestMethod.GET) + .build(); + + InvokeConnectionResponse response = client.connection().invoke(request); + Assert.assertNotNull(response); + Assert.assertNotNull(response.getMetadata()); + Assert.assertEquals("test-request-id", response.getMetadata().get("requestId")); + } } From 4957bf132e4f233c0d782c05548f0ba7e3e814bc Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Mon, 2 Feb 2026 16:47:44 +0530 Subject: [PATCH 06/10] aadarsh-st/SK-2521-fixed test cases --- .../com/skyflow/vault/controller/ConnectionControllerTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java b/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java index 5c884dcf..5ded96b2 100644 --- a/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java +++ b/src/test/java/com/skyflow/vault/controller/ConnectionControllerTests.java @@ -245,7 +245,7 @@ public void testInvokeConnectionWithJsonObjectBody() throws Exception { @Test public void testInvokeConnectionWithNullRequestBody() throws Exception { String jsonResponse = "{\"status\":\"success\"}"; - when(HttpUtility.sendRequest(anyString(), any(URL.class), any(JsonObject.class), anyMap())) + when(HttpUtility.sendRequest(anyString(), any(URL.class), isNull(), anyMap())) .thenReturn(jsonResponse); Skyflow client = Skyflow.builder() From b2fc15215dee4321bf846a724dd3ebcdf14191c1 Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Tue, 3 Feb 2026 13:37:22 +0530 Subject: [PATCH 07/10] aadarsh-st/SK-2521: Removed hardecoded values --- .../java/com/skyflow/utils/Constants.java | 7 +++++++ .../java/com/skyflow/utils/HttpUtility.java | 2 +- src/main/java/com/skyflow/utils/Utils.java | 20 +++++++++---------- .../controller/ConnectionController.java | 12 +++++------ 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/skyflow/utils/Constants.java b/src/main/java/com/skyflow/utils/Constants.java index 1f26cd9d..fd55655e 100644 --- a/src/main/java/com/skyflow/utils/Constants.java +++ b/src/main/java/com/skyflow/utils/Constants.java @@ -60,6 +60,13 @@ private EncodingType() { // Utility class constructor } } + public static final String EMPTY_STRING = ""; + public static final String QUOTE = "\""; + public static final class HttpUtilityExtra { + public static final String RAW_BODY_KEY = "__raw_body__"; + public static final String SDK_GENERATED_PREFIX = "SDK-Generated-"; + private HttpUtilityExtra() {} + } public static final class FileFormatType { public static final String TXT = "txt"; diff --git a/src/main/java/com/skyflow/utils/HttpUtility.java b/src/main/java/com/skyflow/utils/HttpUtility.java index 451be734..f65f692f 100644 --- a/src/main/java/com/skyflow/utils/HttpUtility.java +++ b/src/main/java/com/skyflow/utils/HttpUtility.java @@ -174,7 +174,7 @@ private static String makeFormEncodeKeyValuePair(String key, String value) { try { String encodedKey = URLEncoder.encode(key, StandardCharsets.UTF_8.toString()); String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); - return encodedKey + "=" + encodedValue + "&"; + return encodedKey + Constants.HttpUtility.FORM_ENCODE_SEPARATOR + encodedValue + Constants.HttpUtility.FORM_ENCODE_DELIMITER; } catch (Exception e) { return key + Constants.HttpUtility.FORM_ENCODE_SEPARATOR + value + Constants.HttpUtility.FORM_ENCODE_DELIMITER; } diff --git a/src/main/java/com/skyflow/utils/Utils.java b/src/main/java/com/skyflow/utils/Utils.java index ef3d3148..0826910f 100644 --- a/src/main/java/com/skyflow/utils/Utils.java +++ b/src/main/java/com/skyflow/utils/Utils.java @@ -79,10 +79,10 @@ public static PrivateKey getPrivateKeyFromPem(String pemKey) throws SkyflowExcep PrivateKey privateKey = null; if (pemKey.contains(PKCS8PrivateHeader)) { - privateKeyContent = privateKeyContent.replace(PKCS8PrivateHeader, ""); - privateKeyContent = privateKeyContent.replace(PKCS8PrivateFooter, ""); - privateKeyContent = privateKeyContent.replace("\n", ""); - privateKeyContent = privateKeyContent.replace("\r\n", ""); + privateKeyContent = privateKeyContent.replace(PKCS8PrivateHeader, Constants.EMPTY_STRING); + privateKeyContent = privateKeyContent.replace(PKCS8PrivateFooter, Constants.EMPTY_STRING); + privateKeyContent = privateKeyContent.replace("\n", Constants.EMPTY_STRING); + privateKeyContent = privateKeyContent.replace("\r\n", Constants.EMPTY_STRING); privateKey = parsePkcs8PrivateKey(Base64.decodeBase64(privateKeyContent)); } else { LogUtil.printErrorLog(ErrorLogs.JWT_INVALID_FORMAT.getLog()); @@ -122,16 +122,16 @@ public static String constructConnectionURL(ConnectionConfig config, InvokeConne } if (invokeConnectionRequest.getQueryParams() != null && !invokeConnectionRequest.getQueryParams().isEmpty()) { - filledURL.append("?"); + filledURL.append(Constants.HttpUtility.FORM_ENCODE_DELIMITER); // "?" for (Map.Entry entry : invokeConnectionRequest.getQueryParams().entrySet()) { String key = entry.getKey(); String value = entry.getValue(); try { String encodedKey = URLEncoder.encode(key, StandardCharsets.UTF_8.name()); String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.name()); - filledURL.append(encodedKey).append("=").append(encodedValue).append("&"); + filledURL.append(encodedKey).append(Constants.HttpUtility.FORM_ENCODE_SEPARATOR).append(encodedValue).append(Constants.HttpUtility.FORM_ENCODE_DELIMITER); } catch (Exception e) { - filledURL.append(key).append("=").append(value).append("&"); + filledURL.append(key).append(Constants.HttpUtility.FORM_ENCODE_SEPARATOR).append(value).append(Constants.HttpUtility.FORM_ENCODE_DELIMITER); } } filledURL = new StringBuilder(filledURL.substring(0, filledURL.length() - 1)); @@ -165,7 +165,7 @@ public static JsonObject getMetrics() { InfoLogs.UNABLE_TO_GENERATE_SDK_METRIC.getLog(), Constants.SDK_METRIC_CLIENT_DEVICE_MODEL )); - deviceModel = ""; + deviceModel = Constants.EMPTY_STRING; } // Retrieve OS details @@ -177,7 +177,7 @@ public static JsonObject getMetrics() { InfoLogs.UNABLE_TO_GENERATE_SDK_METRIC.getLog(), Constants.SDK_METRIC_CLIENT_OS_DETAILS )); - osDetails = ""; + osDetails = Constants.EMPTY_STRING; } // Retrieve Java version details @@ -189,7 +189,7 @@ public static JsonObject getMetrics() { InfoLogs.UNABLE_TO_GENERATE_SDK_METRIC.getLog(), Constants.SDK_METRIC_RUNTIME_DETAILS )); - javaVersion = ""; + javaVersion = Constants.EMPTY_STRING; } details.addProperty(Constants.SDK_METRIC_NAME_VERSION, Constants.SDK_METRIC_NAME_VERSION_PREFIX + sdkVersion); details.addProperty(Constants.SDK_METRIC_CLIENT_DEVICE_MODEL, deviceModel); diff --git a/src/main/java/com/skyflow/vault/controller/ConnectionController.java b/src/main/java/com/skyflow/vault/controller/ConnectionController.java index ddb93a9c..06d806c9 100644 --- a/src/main/java/com/skyflow/vault/controller/ConnectionController.java +++ b/src/main/java/com/skyflow/vault/controller/ConnectionController.java @@ -52,10 +52,10 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR RequestMethod requestMethod = invokeConnectionRequest.getMethod(); Object requestBodyObject = invokeConnectionRequest.getRequestBody(); - String requestContentType = headers - .getOrDefault("content-type", "application/json") + String requestContentType = headers + .getOrDefault(Constants.HttpHeader.CONTENT_TYPE, Constants.HttpHeader.CONTENT_TYPE_JSON) .toLowerCase(); - boolean isJsonRequest = requestContentType.contains("application/json"); + boolean isJsonRequest = requestContentType.contains(Constants.HttpHeader.CONTENT_TYPE_JSON); Object processedRequestBody; @@ -64,8 +64,8 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR if (isJsonRequest) { JsonObject jsonWrapper = new JsonObject(); jsonWrapper.addProperty( - "__raw_body__", - (String) requestBodyObject + Constants.HttpUtilityExtra.RAW_BODY_KEY, + (String) requestBodyObject ); processedRequestBody = jsonWrapper; } else { @@ -85,7 +85,7 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR payloadToSend = (JsonObject) processedRequestBody; } else { payloadToSend = new JsonObject(); - payloadToSend.addProperty("__raw_body__", processedRequestBody.toString()); + payloadToSend.addProperty(Constants.HttpUtilityExtra.RAW_BODY_KEY, processedRequestBody.toString()); } String response = HttpUtility.sendRequest(requestMethod.name(), new URL(filledURL), payloadToSend, headers); From 87d151b30e990ace72f0926a728f80063e2f118e Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Tue, 3 Feb 2026 13:47:34 +0530 Subject: [PATCH 08/10] aadarsh-st/SK-2521-Added new constant --- src/main/java/com/skyflow/utils/Constants.java | 2 ++ src/main/java/com/skyflow/utils/HttpUtility.java | 4 ++-- src/main/java/com/skyflow/utils/Utils.java | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/skyflow/utils/Constants.java b/src/main/java/com/skyflow/utils/Constants.java index fd55655e..92a608ac 100644 --- a/src/main/java/com/skyflow/utils/Constants.java +++ b/src/main/java/com/skyflow/utils/Constants.java @@ -34,6 +34,8 @@ public final class Constants { public static final String ERROR_FROM_CLIENT_HEADER_KEY = "error-from-client"; public static final String PROCESSED_FILE_NAME_PREFIX = "processed-"; public static final String DEIDENTIFIED_FILE_PREFIX = "deidentified"; + public static final String CURLY_PLACEHOLDER = "{%s}"; + public static final class HttpHeader { public static final String CONTENT_TYPE = "content-type"; public static final String CONTENT_TYPE_JSON = "application/json"; diff --git a/src/main/java/com/skyflow/utils/HttpUtility.java b/src/main/java/com/skyflow/utils/HttpUtility.java index f65f692f..cc2bc742 100644 --- a/src/main/java/com/skyflow/utils/HttpUtility.java +++ b/src/main/java/com/skyflow/utils/HttpUtility.java @@ -58,8 +58,8 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< String requestContentType = connection.getRequestProperty(Constants.HttpHeader.CONTENT_TYPE); // Check if this is a raw body (XML, plain text, etc.) - if (params.has("__raw_body__") && params.size() == 1) { - input = params.get("__raw_body__").getAsString().getBytes(StandardCharsets.UTF_8); + if (params.has(Constants.HttpUtilityExtra.RAW_BODY_KEY,) && params.size() == 1) { + input = params.get(Constants.HttpUtilityExtra.RAW_BODY_KEY,).getAsString().getBytes(StandardCharsets.UTF_8); } else if (requestContentType != null && requestContentType.contains(Constants.HttpHeader.CONTENT_TYPE_FORM_URLENCODED)) { input = formatJsonToFormEncodedString(params).getBytes(StandardCharsets.UTF_8); } else if (requestContentType != null && requestContentType.contains(Constants.HttpHeader.CONTENT_TYPE_MULTIPART)) { diff --git a/src/main/java/com/skyflow/utils/Utils.java b/src/main/java/com/skyflow/utils/Utils.java index 0826910f..5db83cdd 100644 --- a/src/main/java/com/skyflow/utils/Utils.java +++ b/src/main/java/com/skyflow/utils/Utils.java @@ -114,9 +114,9 @@ public static String constructConnectionURL(ConnectionConfig config, InvokeConne String value = entry.getValue(); try { String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.name()); - filledURL = new StringBuilder(filledURL.toString().replace(String.format("{%s}", key), encodedValue)); + filledURL = new StringBuilder(filledURL.toString().replace(String.format(Constants.CURLY_PLACEHOLDER, key), encodedValue)); } catch (Exception e) { - filledURL = new StringBuilder(filledURL.toString().replace(String.format("{%s}", key), value)); + filledURL = new StringBuilder(filledURL.toString().replace(String.format(Constants.CURLY_PLACEHOLDER, key), value)); } } } From 01404e992267b06943810b6358dcad8677d34094 Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Tue, 3 Feb 2026 14:50:44 +0530 Subject: [PATCH 09/10] aadarsh-st/SK-2521: Fixed undefined error --- src/main/java/com/skyflow/utils/HttpUtility.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/skyflow/utils/HttpUtility.java b/src/main/java/com/skyflow/utils/HttpUtility.java index cc2bc742..fd30ed26 100644 --- a/src/main/java/com/skyflow/utils/HttpUtility.java +++ b/src/main/java/com/skyflow/utils/HttpUtility.java @@ -35,9 +35,9 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod(method); connection.setRequestProperty(Constants.HttpHeader.ACCEPT, Constants.HttpHeader.ACCEPT_ALL); - + boolean hasContentType = headers != null && headers.containsKey(Constants.HttpHeader.CONTENT_TYPE); if (!hasContentType && params != null && !params.isEmpty()) { - connection.setRequestProperty("content-type", "application/json"); + connection.setRequestProperty(Constants.HttpHeader.CONTENT_TYPE, Constants.HttpHeader.CONTENT_TYPE_JSON); } if (headers != null && !headers.isEmpty()) { @@ -58,8 +58,8 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< String requestContentType = connection.getRequestProperty(Constants.HttpHeader.CONTENT_TYPE); // Check if this is a raw body (XML, plain text, etc.) - if (params.has(Constants.HttpUtilityExtra.RAW_BODY_KEY,) && params.size() == 1) { - input = params.get(Constants.HttpUtilityExtra.RAW_BODY_KEY,).getAsString().getBytes(StandardCharsets.UTF_8); + if (params.has(Constants.HttpUtilityExtra.RAW_BODY_KEY) && params.size() == 1) { + input = params.get(Constants.HttpUtilityExtra.RAW_BODY_KEY).getAsString().getBytes(StandardCharsets.UTF_8); } else if (requestContentType != null && requestContentType.contains(Constants.HttpHeader.CONTENT_TYPE_FORM_URLENCODED)) { input = formatJsonToFormEncodedString(params).getBytes(StandardCharsets.UTF_8); } else if (requestContentType != null && requestContentType.contains(Constants.HttpHeader.CONTENT_TYPE_MULTIPART)) { @@ -78,7 +78,7 @@ public static String sendRequest(String method, URL url, JsonObject params, Map< if (requestID != null) { HttpUtility.requestID = requestID.split(Constants.HttpUtility.REQUEST_ID_DELIMITER)[0]; } else { - HttpUtility.requestID = "SDK-Generated-" + UUID.randomUUID(); + HttpUtility.requestID = Constants.HttpUtilityExtra.SDK_GENERATED_PREFIX + UUID.randomUUID(); } Map> responseHeaders = connection.getHeaderFields(); Reader streamReader; From d4a542c020c0e82ffe7763e40b6778935afc71aa Mon Sep 17 00:00:00 2001 From: Aadarsh Date: Tue, 3 Feb 2026 15:05:25 +0530 Subject: [PATCH 10/10] aadarsh-st/SK-2521: fixed test cases --- src/main/java/com/skyflow/utils/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/skyflow/utils/Utils.java b/src/main/java/com/skyflow/utils/Utils.java index 5db83cdd..c53685cc 100644 --- a/src/main/java/com/skyflow/utils/Utils.java +++ b/src/main/java/com/skyflow/utils/Utils.java @@ -122,7 +122,7 @@ public static String constructConnectionURL(ConnectionConfig config, InvokeConne } if (invokeConnectionRequest.getQueryParams() != null && !invokeConnectionRequest.getQueryParams().isEmpty()) { - filledURL.append(Constants.HttpUtility.FORM_ENCODE_DELIMITER); // "?" + filledURL.append("?"); for (Map.Entry entry : invokeConnectionRequest.getQueryParams().entrySet()) { String key = entry.getKey(); String value = entry.getValue();