Skip to content

Commit e517dcf

Browse files
Merge pull request #38 from skyflowapi/release/12.04.2022
Release/12.04.2022
2 parents 172f7c5 + c6b1b1f commit e517dcf

File tree

9 files changed

+219
-11
lines changed

9 files changed

+219
-11
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4+
## [1.5.0] - 2022-04-12
5+
6+
### Added
7+
- support for application/x-www-form-urlencoded and multipart/form-data content-type's in connections.
48

59
## [1.4.1] - 2022-03-29
610

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ This Java SDK is designed to help developers easily implement Skyflow into their
3737

3838
Add this dependency to your project's build file:
3939
```
40-
implementation 'com.skyflow:skyflow-java:1.4.1'
40+
implementation 'com.skyflow:skyflow-java:1.5.0'
4141
```
4242

4343
#### Maven users
@@ -47,7 +47,7 @@ Add this dependency to your project's POM:
4747
<dependency>
4848
<groupId>com.skyflow</groupId>
4949
<artifactId>skyflow-java</artifactId>
50-
<version>1.4.1</version>
50+
<version>1.5.0</version>
5151
</dependency>
5252
```
5353
---

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.skyflow</groupId>
88
<artifactId>skyflow-java</artifactId>
9-
<version>1.4.1</version>
9+
<version>1.5.0</version>
1010
<packaging>jar</packaging>
1111

1212
<name>${project.groupId}:${project.artifactId}</name>

src/main/java/com/skyflow/common/utils/Helpers.java

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@
55
import com.skyflow.entities.InsertRecordInput;
66
import com.skyflow.errors.ErrorCode;
77
import com.skyflow.errors.SkyflowException;
8+
import com.skyflow.logs.DebugLogs;
9+
810
import org.json.simple.JSONArray;
911
import org.json.simple.JSONObject;
1012
import org.json.simple.parser.JSONParser;
1113
import org.json.simple.parser.ParseException;
1214

13-
import java.util.ArrayList;
14-
import java.util.HashMap;
15-
import java.util.List;
16-
import java.util.Map;
15+
import java.util.*;
1716

1817

1918
public final class Helpers {
2019

20+
private static final String LINE_FEED = "\r\n";
2121
public static JSONObject constructInsertRequest(InsertInput recordsInput, InsertOptions options) throws SkyflowException {
2222
JSONObject finalRequest = new JSONObject();
2323
List<JSONObject> requestBodyContent = new ArrayList<JSONObject>();
@@ -161,4 +161,56 @@ public static String appendRequestIdToErrorObj(int status, String error, String
161161
return error;
162162
}
163163

164+
public static String formatJsonToFormEncodedString(JSONObject requestBody){
165+
LogUtil.printDebugLog(DebugLogs.FormatRequestBodyFormUrlFormEncoded.getLog());
166+
StringBuilder formEncodeString = new StringBuilder();
167+
HashMap<String,String> jsonMap = convertJsonToMap(requestBody,"");
168+
169+
for (Map.Entry<String,String> currentEntry : jsonMap.entrySet())
170+
formEncodeString.append(makeFormEncodeKeyValuePair(currentEntry.getKey(),currentEntry.getValue()));
171+
172+
return formEncodeString.substring(0,formEncodeString.length()-1);
173+
}
174+
175+
public static String formatJsonToMultiPartFormDataString(JSONObject requestBody,String boundary){
176+
LogUtil.printDebugLog(DebugLogs.FormatRequestBodyFormData.getLog());
177+
StringBuilder formEncodeString = new StringBuilder();
178+
HashMap<String,String> jsonMap = convertJsonToMap(requestBody,"");
179+
180+
for (Map.Entry<String,String> currentEntry : jsonMap.entrySet())
181+
formEncodeString.append(makeFormDataKeyValuePair(currentEntry.getKey(),currentEntry.getValue(),boundary));
182+
183+
formEncodeString.append(LINE_FEED);
184+
formEncodeString.append("--").append(boundary).append("--").append(LINE_FEED);
185+
186+
return formEncodeString.toString();
187+
}
188+
189+
private static HashMap<String,String> convertJsonToMap(JSONObject json,String rootKey){
190+
HashMap<String,String> currentMap = new HashMap<>();
191+
for (Object key : json.keySet()) {
192+
Object currentValue = json.get(key);
193+
String currentKey = rootKey.length() != 0 ? rootKey + '[' + key.toString() + ']' : rootKey + key.toString();
194+
if(currentValue instanceof JSONObject){
195+
currentMap.putAll(convertJsonToMap((JSONObject) currentValue, currentKey));
196+
}else {
197+
currentMap.put(currentKey,currentValue.toString());
198+
}
199+
}
200+
return currentMap;
201+
}
202+
203+
private static String makeFormEncodeKeyValuePair(String key, String value){
204+
return key+"="+value+"&";
205+
}
206+
207+
private static String makeFormDataKeyValuePair(String key,String value,String boundary){
208+
StringBuilder formDataTextField = new StringBuilder();
209+
formDataTextField.append("--").append(boundary).append(LINE_FEED);
210+
formDataTextField.append("Content-Disposition: form-data; name=\"").append(key).append("\"").append(LINE_FEED);
211+
formDataTextField.append(LINE_FEED);
212+
formDataTextField.append(value).append(LINE_FEED);
213+
214+
return formDataTextField.toString();
215+
}
164216
}

src/main/java/com/skyflow/common/utils/HttpUtility.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,48 @@
1010
import java.nio.charset.StandardCharsets;
1111
import java.util.Map;
1212

13+
import static com.skyflow.common.utils.Helpers.formatJsonToFormEncodedString;
14+
import static com.skyflow.common.utils.Helpers.formatJsonToMultiPartFormDataString;
15+
1316
public final class HttpUtility {
1417

1518
public static String sendRequest(String method, String requestUrl, JSONObject params, Map<String, String> headers) throws IOException, SkyflowException {
1619
HttpURLConnection connection = null;
1720
BufferedReader in = null;
1821
StringBuffer response = null;
22+
String boundary = String.valueOf(System.currentTimeMillis());
1923
try {
2024
URL url = new URL(requestUrl);
2125
connection = (HttpURLConnection) url.openConnection();
2226
connection.setRequestMethod(method);
2327
connection.setRequestProperty("content-type", "application/json");
28+
connection.setRequestProperty("Accept", "*/*");
2429

2530
if (headers != null && headers.size() > 0) {
26-
for (Map.Entry<String, String> entry : headers.entrySet()) {
31+
for (Map.Entry<String, String> entry : headers.entrySet())
2732
connection.setRequestProperty(entry.getKey(), entry.getValue());
33+
34+
// append dynamic boundary if content-type is multipart/form-data
35+
if (headers.containsKey("content-type")) {
36+
if (headers.get("content-type") == "multipart/form-data") {
37+
connection.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary);
38+
}
2839
}
2940
}
30-
3141
if (params != null && params.size() > 0) {
3242
connection.setDoOutput(true);
3343
try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
34-
byte[] input = params.toString().getBytes(StandardCharsets.UTF_8);
44+
byte[] input = null;
45+
String requestContentType = connection.getRequestProperty("content-type");
46+
47+
if (requestContentType.contains("application/x-www-form-urlencoded")) {
48+
input = formatJsonToFormEncodedString(params).getBytes(StandardCharsets.UTF_8);
49+
} else if (requestContentType.contains("multipart/form-data")) {
50+
input = formatJsonToMultiPartFormDataString(params, boundary).getBytes(StandardCharsets.UTF_8);
51+
}else {
52+
input = params.toString().getBytes(StandardCharsets.UTF_8);
53+
}
54+
3555
wr.write(input, 0, input.length);
3656
wr.flush();
3757
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.skyflow.logs;
2+
3+
public enum DebugLogs {
4+
5+
FormatRequestBodyFormUrlFormEncoded("Formatting request body for form-urlencoded content-type"),
6+
FormatRequestBodyFormData("Formatting request body for form-data content-type");
7+
private final String log;
8+
9+
DebugLogs(String log) {
10+
this.log = log;
11+
}
12+
13+
public String getLog() {
14+
return log;
15+
}
16+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.skyflow.common.utils;
2+
3+
import org.json.simple.JSONObject;
4+
import org.junit.Test;
5+
6+
public class HelpersTest {
7+
8+
@Test
9+
public void testFormatJsonToFormEncodedString(){
10+
JSONObject testJson = new JSONObject();
11+
testJson.put("key1","value1");
12+
JSONObject nestedObj = new JSONObject();
13+
nestedObj.put("key2","value2");
14+
testJson.put("nest",nestedObj);
15+
16+
String testResponse = Helpers.formatJsonToFormEncodedString(testJson);
17+
System.out.println(testResponse);
18+
assert testResponse.contains("key1=value1");
19+
assert testResponse.contains("nest[key2]=value2");
20+
}
21+
22+
@Test
23+
public void testFormatJsonToMultiPartFormDataString(){
24+
JSONObject testJson = new JSONObject();
25+
testJson.put("key1","value1");
26+
JSONObject nestedObj = new JSONObject();
27+
nestedObj.put("key2","value2");
28+
testJson.put("nest",nestedObj);
29+
String testBoundary = "123";
30+
String testResponse = Helpers.formatJsonToMultiPartFormDataString(testJson,testBoundary);
31+
assert testResponse.contains("--"+testBoundary);
32+
assert testResponse.contains("--"+testBoundary+"--");
33+
assert testResponse.contains("Content-Disposition: form-data; name=\"key1\"");
34+
assert testResponse.contains("value1");
35+
assert testResponse.contains("Content-Disposition: form-data; name=\"nest[key2]\"");
36+
assert testResponse.contains("value2");
37+
}
38+
}

src/test/java/com/skyflow/serviceaccount/util/TokenTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class TokenTest {
2323
@Test
2424
public void testInvalidFilePath() {
2525
try {
26-
Token.generateBearerToken("");
26+
Token.GenerateToken("");
2727
} catch (SkyflowException exception) {
2828
assertEquals(exception.getMessage(), ErrorCode.EmptyFilePath.getDescription());
2929
}

src/test/java/com/skyflow/vault/InvokeConnectionTest.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.io.IOException;
2222

23+
import static org.junit.Assert.fail;
2324
import static org.mockito.ArgumentMatchers.anyString;
2425

2526

@@ -34,6 +35,7 @@ public String getBearerToken() throws Exception {
3435
@RunWith(PowerMockRunner.class)
3536
@PrepareForTest(fullyQualifiedNames = "com.skyflow.common.utils.TokenUtils")
3637
public class InvokeConnectionTest {
38+
private static final String INVALID_EXCEPTION_THROWN = "Should not have thrown any exception";
3739
private JSONObject testConfig;
3840
private static Skyflow skyflowClient;
3941

@@ -84,8 +86,10 @@ public void testInvokeConnectionValidInput() {
8486
Assert.assertEquals(gatewayResponse.toJSONString(), mockResponse);
8587
} catch (SkyflowException exception) {
8688
Assert.assertNull(exception);
89+
fail(INVALID_EXCEPTION_THROWN);
8790
} catch (IOException exception) {
8891
exception.printStackTrace();
92+
fail(INVALID_EXCEPTION_THROWN);
8993
}
9094

9195

@@ -158,4 +162,78 @@ public void testInvokeConnectionInvalidMethodName() {
158162
}
159163
}
160164

165+
@Test
166+
@PrepareForTest(fullyQualifiedNames = {"com.skyflow.common.utils.HttpUtility", "com.skyflow.common.utils.TokenUtils"})
167+
public void testInvokeConnectionWithFormEncoded() {
168+
JSONObject testConfig = new JSONObject();
169+
testConfig.put("connectionURL", "https://testgatewayurl.com/");
170+
testConfig.put("methodName", RequestMethod.POST);
171+
172+
JSONObject requestHeadersJson = new JSONObject();
173+
requestHeadersJson.put("content-type", "application/x-www-form-urlencoded");
174+
testConfig.put("requestHeader", requestHeadersJson);
175+
176+
JSONObject testJson = new JSONObject();
177+
testJson.put("key1","value1");
178+
JSONObject nestedObj = new JSONObject();
179+
nestedObj.put("key2","value2");
180+
testJson.put("nest",nestedObj);
181+
182+
testConfig.put("requestBody", testJson);
183+
184+
try {
185+
PowerMockito.mockStatic(HttpUtility.class);
186+
String mockResponse = "{\"id\":\"12345\"}";
187+
PowerMockito.when(HttpUtility.sendRequest(anyString(), anyString(), ArgumentMatchers.<JSONObject>any(), ArgumentMatchers.<String, String>anyMap())).thenReturn(mockResponse);
188+
JSONObject gatewayResponse = skyflowClient.invokeConnection(testConfig);
189+
190+
Assert.assertNotNull(gatewayResponse);
191+
Assert.assertEquals(gatewayResponse.toJSONString(), mockResponse);
192+
} catch (SkyflowException exception) {
193+
Assert.assertNull(exception);
194+
fail(INVALID_EXCEPTION_THROWN);
195+
} catch (IOException exception) {
196+
exception.printStackTrace();
197+
fail(INVALID_EXCEPTION_THROWN);
198+
}
199+
200+
}
201+
202+
@Test
203+
@PrepareForTest(fullyQualifiedNames = {"com.skyflow.common.utils.HttpUtility", "com.skyflow.common.utils.TokenUtils"})
204+
public void testInvokeConnectionWithMultipartFormData() {
205+
JSONObject testConfig = new JSONObject();
206+
testConfig.put("connectionURL", "https://testgatewayurl.com/");
207+
testConfig.put("methodName", RequestMethod.POST);
208+
209+
JSONObject requestHeadersJson = new JSONObject();
210+
requestHeadersJson.put("content-type", "multipart/form-data");
211+
testConfig.put("requestHeader", requestHeadersJson);
212+
213+
JSONObject testJson = new JSONObject();
214+
testJson.put("key1","value1");
215+
JSONObject nestedObj = new JSONObject();
216+
nestedObj.put("key2","value2");
217+
testJson.put("nest",nestedObj);
218+
219+
testConfig.put("requestBody", testJson);
220+
221+
try {
222+
PowerMockito.mockStatic(HttpUtility.class);
223+
String mockResponse = "{\"id\":\"12345\"}";
224+
PowerMockito.when(HttpUtility.sendRequest(anyString(), anyString(), ArgumentMatchers.<JSONObject>any(), ArgumentMatchers.<String, String>anyMap())).thenReturn(mockResponse);
225+
JSONObject gatewayResponse = skyflowClient.invokeConnection(testConfig);
226+
227+
Assert.assertNotNull(gatewayResponse);
228+
Assert.assertEquals(gatewayResponse.toJSONString(), mockResponse);
229+
} catch (SkyflowException exception) {
230+
Assert.assertNull(exception);
231+
fail(INVALID_EXCEPTION_THROWN);
232+
} catch (IOException exception) {
233+
exception.printStackTrace();
234+
fail(INVALID_EXCEPTION_THROWN);
235+
}
236+
237+
}
238+
161239
}

0 commit comments

Comments
 (0)