tharak-android 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +1 -0
- package/build.gradle +45 -0
- package/consumer-rules.pro +0 -0
- package/libs/vital-sdk.aar +0 -0
- package/package.json +22 -0
- package/proguard-rules.pro +21 -0
- package/src/androidTest/androidTest.iml +11 -0
- package/src/androidTest/java/org/tharak/core/ExampleInstrumentedTest.java +27 -0
- package/src/androidTest/java/org/thiragatisoft/core/ExampleInstrumentedTest.java +26 -0
- package/src/main/AndroidManifest.xml +5 -0
- package/src/main/java/org/thiragatisoft/core/AppUtils.java +31 -0
- package/src/main/java/org/thiragatisoft/core/FileSelector.java +162 -0
- package/src/main/java/org/thiragatisoft/core/MainActivity.java +27 -0
- package/src/main/java/org/thiragatisoft/core/RestClient.java +298 -0
- package/src/main/java/org/thiragatisoft/core/VitalActivity.java +612 -0
- package/src/main/java/org/thiragatisoft/core/VitalsPlugin.java +15 -0
- package/src/main/java/org/thiragatisoft/core/VolleyMultipartRequest.java +218 -0
- package/src/main/java/org/thiragatisoft/core/http/CapacitorCookieManager.java +175 -0
- package/src/main/java/org/thiragatisoft/core/http/CapacitorHttpUrlConnection.java +408 -0
- package/src/main/java/org/thiragatisoft/core/http/FilesystemUtils.java +65 -0
- package/src/main/java/org/thiragatisoft/core/http/FormUploader.java +219 -0
- package/src/main/java/org/thiragatisoft/core/http/Http.java +275 -0
- package/src/main/java/org/thiragatisoft/core/http/HttpRequestHandler.java +515 -0
- package/src/main/java/org/thiragatisoft/core/http/ICapacitorHttpUrlConnection.java +15 -0
- package/src/main/java/org/thiragatisoft/core/http/JSValue.java +68 -0
- package/src/main/java/org/thiragatisoft/core/http/MimeType.java +17 -0
- package/src/main/main.iml +12 -0
- package/src/test/java/org/tharak/ExampleUnitTest.java +17 -0
- package/src/test/java/org/tharak/JSObjectTest.java +209 -0
- package/src/test/java/org/tharak/PluginMethodHandleTest.java +44 -0
- package/src/test/java/org/tharak/util/HostMaskTest.java +70 -0
- package/src/test/java/org/thiragatisoft/core/ExampleUnitTest.java +17 -0
- package/src/test/test.iml +11 -0
@@ -0,0 +1,515 @@
|
|
1
|
+
package org.thiragatisoft.core.http;
|
2
|
+
|
3
|
+
import android.content.Context;
|
4
|
+
import android.text.TextUtils;
|
5
|
+
import android.util.Base64;
|
6
|
+
import com.getcapacitor.JSArray;
|
7
|
+
import com.getcapacitor.JSObject;
|
8
|
+
import com.getcapacitor.PluginCall;
|
9
|
+
import java.io.BufferedReader;
|
10
|
+
import java.io.ByteArrayOutputStream;
|
11
|
+
import java.io.File;
|
12
|
+
import java.io.FileOutputStream;
|
13
|
+
import java.io.IOException;
|
14
|
+
import java.io.InputStream;
|
15
|
+
import java.io.InputStreamReader;
|
16
|
+
import java.net.HttpURLConnection;
|
17
|
+
import java.net.MalformedURLException;
|
18
|
+
import java.net.URI;
|
19
|
+
import java.net.URISyntaxException;
|
20
|
+
import java.net.URL;
|
21
|
+
import java.util.Iterator;
|
22
|
+
import java.util.List;
|
23
|
+
import java.util.Map;
|
24
|
+
import org.json.JSONArray;
|
25
|
+
import org.json.JSONException;
|
26
|
+
import org.json.JSONObject;
|
27
|
+
|
28
|
+
public class HttpRequestHandler {
|
29
|
+
|
30
|
+
/**
|
31
|
+
* An enum specifying conventional HTTP Response Types
|
32
|
+
* See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
|
33
|
+
*/
|
34
|
+
public enum ResponseType {
|
35
|
+
ARRAY_BUFFER("arraybuffer"),
|
36
|
+
BLOB("blob"),
|
37
|
+
DOCUMENT("document"),
|
38
|
+
JSON("json"),
|
39
|
+
TEXT("text");
|
40
|
+
|
41
|
+
private final String name;
|
42
|
+
|
43
|
+
ResponseType(String name) {
|
44
|
+
this.name = name;
|
45
|
+
}
|
46
|
+
|
47
|
+
static final ResponseType DEFAULT = TEXT;
|
48
|
+
|
49
|
+
static ResponseType parse(String value) {
|
50
|
+
for (ResponseType responseType : values()) {
|
51
|
+
if (responseType.name.equalsIgnoreCase(value)) {
|
52
|
+
return responseType;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
return DEFAULT;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Internal builder class for building a CapacitorHttpUrlConnection
|
61
|
+
*/
|
62
|
+
private static class HttpURLConnectionBuilder {
|
63
|
+
|
64
|
+
private Integer connectTimeout;
|
65
|
+
private Integer readTimeout;
|
66
|
+
private Boolean disableRedirects;
|
67
|
+
private JSObject headers;
|
68
|
+
private String method;
|
69
|
+
private URL url;
|
70
|
+
|
71
|
+
private CapacitorHttpUrlConnection connection;
|
72
|
+
|
73
|
+
public HttpURLConnectionBuilder setConnectTimeout(Integer connectTimeout) {
|
74
|
+
this.connectTimeout = connectTimeout;
|
75
|
+
return this;
|
76
|
+
}
|
77
|
+
|
78
|
+
public HttpURLConnectionBuilder setReadTimeout(Integer readTimeout) {
|
79
|
+
this.readTimeout = readTimeout;
|
80
|
+
return this;
|
81
|
+
}
|
82
|
+
|
83
|
+
public HttpURLConnectionBuilder setDisableRedirects(Boolean disableRedirects) {
|
84
|
+
this.disableRedirects = disableRedirects;
|
85
|
+
return this;
|
86
|
+
}
|
87
|
+
|
88
|
+
public HttpURLConnectionBuilder setHeaders(JSObject headers) {
|
89
|
+
this.headers = headers;
|
90
|
+
return this;
|
91
|
+
}
|
92
|
+
|
93
|
+
public HttpURLConnectionBuilder setMethod(String method) {
|
94
|
+
this.method = method;
|
95
|
+
return this;
|
96
|
+
}
|
97
|
+
|
98
|
+
public HttpURLConnectionBuilder setUrl(URL url) {
|
99
|
+
this.url = url;
|
100
|
+
return this;
|
101
|
+
}
|
102
|
+
|
103
|
+
public HttpURLConnectionBuilder openConnection() throws IOException {
|
104
|
+
connection = new CapacitorHttpUrlConnection((HttpURLConnection) url.openConnection());
|
105
|
+
|
106
|
+
connection.setAllowUserInteraction(false);
|
107
|
+
connection.setRequestMethod(method);
|
108
|
+
|
109
|
+
if (connectTimeout != null) connection.setConnectTimeout(connectTimeout);
|
110
|
+
if (readTimeout != null) connection.setReadTimeout(readTimeout);
|
111
|
+
if (disableRedirects != null) connection.setDisableRedirects(disableRedirects);
|
112
|
+
|
113
|
+
connection.setRequestHeaders(headers);
|
114
|
+
return this;
|
115
|
+
}
|
116
|
+
|
117
|
+
public HttpURLConnectionBuilder setUrlParams(JSObject params) throws MalformedURLException, URISyntaxException, JSONException {
|
118
|
+
return this.setUrlParams(params, true);
|
119
|
+
}
|
120
|
+
|
121
|
+
public HttpURLConnectionBuilder setUrlParams(JSObject params, boolean shouldEncode)
|
122
|
+
throws URISyntaxException, MalformedURLException {
|
123
|
+
String initialQuery = url.getQuery();
|
124
|
+
String initialQueryBuilderStr = initialQuery == null ? "" : initialQuery;
|
125
|
+
|
126
|
+
Iterator<String> keys = params.keys();
|
127
|
+
|
128
|
+
if (!keys.hasNext()) {
|
129
|
+
return this;
|
130
|
+
}
|
131
|
+
|
132
|
+
StringBuilder urlQueryBuilder = new StringBuilder(initialQueryBuilderStr);
|
133
|
+
|
134
|
+
// Build the new query string
|
135
|
+
while (keys.hasNext()) {
|
136
|
+
String key = keys.next();
|
137
|
+
|
138
|
+
// Attempt as JSONArray and fallback to string if it fails
|
139
|
+
try {
|
140
|
+
StringBuilder value = new StringBuilder();
|
141
|
+
JSONArray arr = params.getJSONArray(key);
|
142
|
+
for (int x = 0; x < arr.length(); x++) {
|
143
|
+
value.append(key).append("=").append(arr.getString(x));
|
144
|
+
if (x != arr.length() - 1) {
|
145
|
+
value.append("&");
|
146
|
+
}
|
147
|
+
}
|
148
|
+
if (urlQueryBuilder.length() > 0) {
|
149
|
+
urlQueryBuilder.append("&");
|
150
|
+
}
|
151
|
+
urlQueryBuilder.append(value);
|
152
|
+
} catch (JSONException e) {
|
153
|
+
if (urlQueryBuilder.length() > 0) {
|
154
|
+
urlQueryBuilder.append("&");
|
155
|
+
}
|
156
|
+
urlQueryBuilder.append(key).append("=").append(params.getString(key));
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
160
|
+
String urlQuery = urlQueryBuilder.toString();
|
161
|
+
|
162
|
+
URI uri = url.toURI();
|
163
|
+
if (shouldEncode) {
|
164
|
+
URI encodedUri = new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), urlQuery, uri.getFragment());
|
165
|
+
this.url = encodedUri.toURL();
|
166
|
+
} else {
|
167
|
+
String unEncodedUrlString = uri.getScheme() + "://" + uri.getAuthority() + uri.getPath() + ((!urlQuery.equals("")) ? "?" + urlQuery : "") + ((uri.getFragment() != null) ? uri.getFragment() : "");
|
168
|
+
this.url = new URL(unEncodedUrlString);
|
169
|
+
}
|
170
|
+
|
171
|
+
return this;
|
172
|
+
}
|
173
|
+
|
174
|
+
public CapacitorHttpUrlConnection build() {
|
175
|
+
return connection;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
/**
|
180
|
+
* Builds an HTTP Response given CapacitorHttpUrlConnection and ResponseType objects.
|
181
|
+
* Defaults to ResponseType.DEFAULT
|
182
|
+
* @param connection The CapacitorHttpUrlConnection to respond with
|
183
|
+
* @throws IOException Thrown if the InputStream is unable to be parsed correctly
|
184
|
+
* @throws JSONException Thrown if the JSON is unable to be parsed
|
185
|
+
*/
|
186
|
+
private static JSObject buildResponse(CapacitorHttpUrlConnection connection) throws IOException, JSONException {
|
187
|
+
return buildResponse(connection, ResponseType.DEFAULT);
|
188
|
+
}
|
189
|
+
|
190
|
+
/**
|
191
|
+
* Builds an HTTP Response given CapacitorHttpUrlConnection and ResponseType objects
|
192
|
+
* @param connection The CapacitorHttpUrlConnection to respond with
|
193
|
+
* @param responseType The requested ResponseType
|
194
|
+
* @return A JSObject that contains the HTTPResponse to return to the browser
|
195
|
+
* @throws IOException Thrown if the InputStream is unable to be parsed correctly
|
196
|
+
* @throws JSONException Thrown if the JSON is unable to be parsed
|
197
|
+
*/
|
198
|
+
private static JSObject buildResponse(CapacitorHttpUrlConnection connection, ResponseType responseType)
|
199
|
+
throws IOException, JSONException {
|
200
|
+
int statusCode = connection.getResponseCode();
|
201
|
+
|
202
|
+
JSObject output = new JSObject();
|
203
|
+
output.put("status", statusCode);
|
204
|
+
output.put("headers", buildResponseHeaders(connection));
|
205
|
+
output.put("url", connection.getURL());
|
206
|
+
output.put("body", readData(connection, responseType));
|
207
|
+
|
208
|
+
InputStream errorStream = connection.getErrorStream();
|
209
|
+
if (errorStream != null) {
|
210
|
+
output.put("error", true);
|
211
|
+
}
|
212
|
+
|
213
|
+
return output;
|
214
|
+
}
|
215
|
+
|
216
|
+
/**
|
217
|
+
* Read the existing ICapacitorHttpUrlConnection data
|
218
|
+
* @param connection The ICapacitorHttpUrlConnection object to read in
|
219
|
+
* @param responseType The type of HTTP response to return to the API
|
220
|
+
* @return The parsed data from the connection
|
221
|
+
* @throws IOException Thrown if the InputStreams cannot be properly parsed
|
222
|
+
* @throws JSONException Thrown if the JSON is malformed when parsing as JSON
|
223
|
+
*/
|
224
|
+
static Object readData(ICapacitorHttpUrlConnection connection, ResponseType responseType) throws IOException, JSONException {
|
225
|
+
InputStream errorStream = connection.getErrorStream();
|
226
|
+
String contentType = connection.getHeaderField("Content-Type");
|
227
|
+
|
228
|
+
if (errorStream != null) {
|
229
|
+
if (isOneOf(contentType, MimeType.APPLICATION_JSON, MimeType.APPLICATION_VND_API_JSON)) {
|
230
|
+
return parseJSON(readStreamAsString(errorStream));
|
231
|
+
} else {
|
232
|
+
return readStreamAsString(errorStream);
|
233
|
+
}
|
234
|
+
} else if (contentType != null && contentType.contains(MimeType.APPLICATION_JSON.getValue())) {
|
235
|
+
// backward compatibility
|
236
|
+
return parseJSON(readStreamAsString(connection.getInputStream()));
|
237
|
+
} else {
|
238
|
+
InputStream stream = connection.getInputStream();
|
239
|
+
switch (responseType) {
|
240
|
+
case ARRAY_BUFFER:
|
241
|
+
case BLOB:
|
242
|
+
return readStreamAsBase64(stream);
|
243
|
+
case JSON:
|
244
|
+
return parseJSON(readStreamAsString(stream));
|
245
|
+
case DOCUMENT:
|
246
|
+
case TEXT:
|
247
|
+
default:
|
248
|
+
return readStreamAsString(stream);
|
249
|
+
}
|
250
|
+
}
|
251
|
+
}
|
252
|
+
|
253
|
+
/**
|
254
|
+
* Helper function for determining if the Content-Type is a typeof an existing Mime-Type
|
255
|
+
* @param contentType The Content-Type string to check for
|
256
|
+
* @param mimeTypes The Mime-Type values to check against
|
257
|
+
* @return
|
258
|
+
*/
|
259
|
+
private static boolean isOneOf(String contentType, MimeType... mimeTypes) {
|
260
|
+
if (contentType != null) {
|
261
|
+
for (MimeType mimeType : mimeTypes) {
|
262
|
+
if (contentType.contains(mimeType.getValue())) {
|
263
|
+
return true;
|
264
|
+
}
|
265
|
+
}
|
266
|
+
}
|
267
|
+
return false;
|
268
|
+
}
|
269
|
+
|
270
|
+
/**
|
271
|
+
* Build the JSObject response headers based on the connection header map
|
272
|
+
* @param connection The CapacitorHttpUrlConnection connection
|
273
|
+
* @return A JSObject of the header values from the CapacitorHttpUrlConnection
|
274
|
+
*/
|
275
|
+
private static JSObject buildResponseHeaders(CapacitorHttpUrlConnection connection) {
|
276
|
+
JSObject output = new JSObject();
|
277
|
+
|
278
|
+
for (Map.Entry<String, List<String>> entry : connection.getHeaderFields().entrySet()) {
|
279
|
+
String valuesString = TextUtils.join(", ", entry.getValue());
|
280
|
+
output.put(entry.getKey(), valuesString);
|
281
|
+
}
|
282
|
+
|
283
|
+
return output;
|
284
|
+
}
|
285
|
+
|
286
|
+
/**
|
287
|
+
* Returns a JSObject or a JSArray based on a string-ified input
|
288
|
+
* @param input String-ified JSON that needs parsing
|
289
|
+
* @return A JSObject or JSArray
|
290
|
+
* @throws JSONException thrown if the JSON is malformed
|
291
|
+
*/
|
292
|
+
private static Object parseJSON(String input) throws JSONException {
|
293
|
+
JSONObject json = new JSONObject();
|
294
|
+
try {
|
295
|
+
if ("null".equals(input.trim())) {
|
296
|
+
return JSONObject.NULL;
|
297
|
+
} else if ("true".equals(input.trim())) {
|
298
|
+
return new JSONObject().put("flag", "true");
|
299
|
+
} else if ("false".equals(input.trim())) {
|
300
|
+
return new JSONObject().put("flag", "false");
|
301
|
+
} else {
|
302
|
+
try {
|
303
|
+
return new JSObject(input);
|
304
|
+
} catch (JSONException e) {
|
305
|
+
return new JSArray(input);
|
306
|
+
}
|
307
|
+
}
|
308
|
+
} catch (JSONException e) {
|
309
|
+
return new JSArray(input);
|
310
|
+
}
|
311
|
+
}
|
312
|
+
|
313
|
+
/**
|
314
|
+
* Returns a string based on a base64 InputStream
|
315
|
+
* @param in The base64 InputStream to convert to a String
|
316
|
+
* @return String value of InputStream
|
317
|
+
* @throws IOException thrown if the InputStream is unable to be read as base64
|
318
|
+
*/
|
319
|
+
private static String readStreamAsBase64(InputStream in) throws IOException {
|
320
|
+
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
321
|
+
byte[] buffer = new byte[1024];
|
322
|
+
int readBytes;
|
323
|
+
while ((readBytes = in.read(buffer)) != -1) {
|
324
|
+
out.write(buffer, 0, readBytes);
|
325
|
+
}
|
326
|
+
byte[] result = out.toByteArray();
|
327
|
+
return Base64.encodeToString(result, 0, result.length, Base64.DEFAULT);
|
328
|
+
}
|
329
|
+
}
|
330
|
+
|
331
|
+
/**
|
332
|
+
* Returns a string based on an InputStream
|
333
|
+
* @param in The InputStream to convert to a String
|
334
|
+
* @return String value of InputStream
|
335
|
+
* @throws IOException thrown if the InputStream is unable to be read
|
336
|
+
*/
|
337
|
+
private static String readStreamAsString(InputStream in) throws IOException {
|
338
|
+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
|
339
|
+
StringBuilder builder = new StringBuilder();
|
340
|
+
String line = reader.readLine();
|
341
|
+
while (line != null) {
|
342
|
+
builder.append(line);
|
343
|
+
line = reader.readLine();
|
344
|
+
if (line != null) {
|
345
|
+
builder.append(System.getProperty("line.separator"));
|
346
|
+
}
|
347
|
+
}
|
348
|
+
return builder.toString();
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
/**
|
353
|
+
* Makes an Http Request based on the PluginCall parameters
|
354
|
+
* @param call The Capacitor PluginCall that contains the options need for an Http request
|
355
|
+
* @param httpMethod The HTTP method that overrides the PluginCall HTTP method
|
356
|
+
* @throws IOException throws an IO request when a connection can't be made
|
357
|
+
* @throws URISyntaxException thrown when the URI is malformed
|
358
|
+
* @throws JSONException thrown when the incoming JSON is malformed
|
359
|
+
*/
|
360
|
+
public static JSObject request(PluginCall call, String httpMethod) throws IOException, URISyntaxException, JSONException {
|
361
|
+
String urlString = call.getString("url", "");
|
362
|
+
JSObject headers = call.getObject("headers");
|
363
|
+
JSObject params = call.getObject("params");
|
364
|
+
Integer connectTimeout = call.getInt("connectTimeout");
|
365
|
+
Integer readTimeout = call.getInt("readTimeout");
|
366
|
+
Boolean disableRedirects = call.getBoolean("disableRedirects");
|
367
|
+
Boolean shouldEncode = call.getBoolean("shouldEncodeUrlParams", true);
|
368
|
+
ResponseType responseType = ResponseType.parse(call.getString("responseType"));
|
369
|
+
|
370
|
+
String method = httpMethod != null ? httpMethod.toUpperCase() : call.getString("method", "").toUpperCase();
|
371
|
+
|
372
|
+
boolean isHttpMutate = method.equals("DELETE") || method.equals("PATCH") || method.equals("POST") || method.equals("PUT");
|
373
|
+
|
374
|
+
URL url = new URL(urlString);
|
375
|
+
HttpURLConnectionBuilder connectionBuilder = new HttpURLConnectionBuilder()
|
376
|
+
.setUrl(url)
|
377
|
+
.setMethod(method)
|
378
|
+
.setHeaders(headers)
|
379
|
+
.setUrlParams(params, shouldEncode)
|
380
|
+
.setConnectTimeout(connectTimeout)
|
381
|
+
.setReadTimeout(readTimeout)
|
382
|
+
.setDisableRedirects(disableRedirects)
|
383
|
+
.openConnection();
|
384
|
+
|
385
|
+
CapacitorHttpUrlConnection connection = connectionBuilder.build();
|
386
|
+
|
387
|
+
// Set HTTP body on a non GET or HEAD request
|
388
|
+
if (isHttpMutate) {
|
389
|
+
JSValue data = new JSValue(call, "body");
|
390
|
+
if (data.getValue() != null) {
|
391
|
+
connection.setDoOutput(true);
|
392
|
+
connection.setRequestBody(call, data);
|
393
|
+
}
|
394
|
+
}
|
395
|
+
|
396
|
+
connection.connect();
|
397
|
+
|
398
|
+
return buildResponse(connection, responseType);
|
399
|
+
}
|
400
|
+
|
401
|
+
/**
|
402
|
+
* Makes an Http Request to download a file based on the PluginCall parameters
|
403
|
+
* @param call The Capacitor PluginCall that contains the options need for an Http request
|
404
|
+
* @param context The Android Context required for writing to the filesystem
|
405
|
+
* @param progress The emitter which notifies listeners on downloading progression
|
406
|
+
* @throws IOException throws an IO request when a connection can't be made
|
407
|
+
* @throws URISyntaxException thrown when the URI is malformed
|
408
|
+
*/
|
409
|
+
public static JSObject downloadFile(PluginCall call, Context context, ProgressEmitter progress)
|
410
|
+
throws IOException, URISyntaxException, JSONException {
|
411
|
+
String urlString = call.getString("url");
|
412
|
+
String method = call.getString("method", "GET").toUpperCase();
|
413
|
+
String filePath = call.getString("filePath");
|
414
|
+
String fileDirectory = call.getString("fileDirectory", FilesystemUtils.DIRECTORY_DOCUMENTS);
|
415
|
+
JSObject headers = call.getObject("headers");
|
416
|
+
JSObject params = call.getObject("params");
|
417
|
+
Integer connectTimeout = call.getInt("connectTimeout");
|
418
|
+
Integer readTimeout = call.getInt("readTimeout");
|
419
|
+
|
420
|
+
final URL url = new URL(urlString);
|
421
|
+
final File file = FilesystemUtils.getFileObject(context, filePath, fileDirectory);
|
422
|
+
|
423
|
+
HttpURLConnectionBuilder connectionBuilder = new HttpURLConnectionBuilder()
|
424
|
+
.setUrl(url)
|
425
|
+
.setMethod(method)
|
426
|
+
.setHeaders(headers)
|
427
|
+
.setUrlParams(params)
|
428
|
+
.setConnectTimeout(connectTimeout)
|
429
|
+
.setReadTimeout(readTimeout)
|
430
|
+
.openConnection();
|
431
|
+
|
432
|
+
ICapacitorHttpUrlConnection connection = connectionBuilder.build();
|
433
|
+
InputStream connectionInputStream = connection.getInputStream();
|
434
|
+
|
435
|
+
FileOutputStream fileOutputStream = new FileOutputStream(file, false);
|
436
|
+
|
437
|
+
String contentLength = connection.getHeaderField("content-length");
|
438
|
+
int bytes = 0;
|
439
|
+
int maxBytes = 0;
|
440
|
+
|
441
|
+
try {
|
442
|
+
maxBytes = contentLength != null ? Integer.parseInt(contentLength) : 0;
|
443
|
+
} catch (NumberFormatException e) {
|
444
|
+
maxBytes = 0;
|
445
|
+
}
|
446
|
+
|
447
|
+
byte[] buffer = new byte[1024];
|
448
|
+
int len;
|
449
|
+
|
450
|
+
while ((len = connectionInputStream.read(buffer)) > 0) {
|
451
|
+
fileOutputStream.write(buffer, 0, len);
|
452
|
+
|
453
|
+
bytes += len;
|
454
|
+
progress.emit(bytes, maxBytes);
|
455
|
+
}
|
456
|
+
|
457
|
+
connectionInputStream.close();
|
458
|
+
fileOutputStream.close();
|
459
|
+
|
460
|
+
return new JSObject() {
|
461
|
+
{
|
462
|
+
put("path", file.getAbsolutePath());
|
463
|
+
}
|
464
|
+
};
|
465
|
+
}
|
466
|
+
|
467
|
+
/**
|
468
|
+
* Makes an Http Request to upload a file based on the PluginCall parameters
|
469
|
+
* @param call The Capacitor PluginCall that contains the options need for an Http request
|
470
|
+
* @param context The Android Context required for writing to the filesystem
|
471
|
+
* @throws IOException throws an IO request when a connection can't be made
|
472
|
+
* @throws URISyntaxException thrown when the URI is malformed
|
473
|
+
* @throws JSONException thrown when malformed JSON is passed into the function
|
474
|
+
*/
|
475
|
+
public static JSObject uploadFile(PluginCall call, Context context) throws IOException, URISyntaxException, JSONException {
|
476
|
+
String urlString = call.getString("url");
|
477
|
+
String method = call.getString("method", "POST").toUpperCase();
|
478
|
+
String filePath = call.getString("filePath");
|
479
|
+
String fileDirectory = call.getString("fileDirectory", FilesystemUtils.DIRECTORY_DOCUMENTS);
|
480
|
+
String name = call.getString("name", "file");
|
481
|
+
Integer connectTimeout = call.getInt("connectTimeout");
|
482
|
+
Integer readTimeout = call.getInt("readTimeout");
|
483
|
+
JSObject headers = call.getObject("headers");
|
484
|
+
JSObject params = call.getObject("params");
|
485
|
+
JSObject data = call.getObject("data");
|
486
|
+
ResponseType responseType = ResponseType.parse(call.getString("responseType"));
|
487
|
+
|
488
|
+
URL url = new URL(urlString);
|
489
|
+
|
490
|
+
File file = FilesystemUtils.getFileObject(context, filePath, fileDirectory);
|
491
|
+
|
492
|
+
HttpURLConnectionBuilder connectionBuilder = new HttpURLConnectionBuilder()
|
493
|
+
.setUrl(url)
|
494
|
+
.setMethod(method)
|
495
|
+
.setHeaders(headers)
|
496
|
+
.setUrlParams(params)
|
497
|
+
.setConnectTimeout(connectTimeout)
|
498
|
+
.setReadTimeout(readTimeout)
|
499
|
+
.openConnection();
|
500
|
+
|
501
|
+
CapacitorHttpUrlConnection connection = connectionBuilder.build();
|
502
|
+
connection.setDoOutput(true);
|
503
|
+
|
504
|
+
FormUploader builder = new FormUploader(connection.getHttpConnection());
|
505
|
+
builder.addFilePart(name, file, data);
|
506
|
+
builder.finish();
|
507
|
+
|
508
|
+
return buildResponse(connection, responseType);
|
509
|
+
}
|
510
|
+
|
511
|
+
@FunctionalInterface
|
512
|
+
public interface ProgressEmitter {
|
513
|
+
void emit(Integer bytes, Integer contentLength);
|
514
|
+
}
|
515
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
package org.thiragatisoft.core.http;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
import java.io.InputStream;
|
5
|
+
|
6
|
+
/**
|
7
|
+
* This interface was extracted from {@link CapacitorHttpUrlConnection} to enable mocking that class.
|
8
|
+
*/
|
9
|
+
interface ICapacitorHttpUrlConnection {
|
10
|
+
InputStream getErrorStream();
|
11
|
+
|
12
|
+
String getHeaderField(String name);
|
13
|
+
|
14
|
+
InputStream getInputStream() throws IOException;
|
15
|
+
}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
package org.thiragatisoft.core.http;
|
2
|
+
|
3
|
+
import com.getcapacitor.JSArray;
|
4
|
+
import com.getcapacitor.JSObject;
|
5
|
+
import com.getcapacitor.PluginCall;
|
6
|
+
import org.json.JSONException;
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Represents a single user-data value of any type on the capacitor PluginCall object.
|
10
|
+
*/
|
11
|
+
public class JSValue {
|
12
|
+
|
13
|
+
private final Object value;
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @param call The capacitor plugin call, used for accessing the value safely.
|
17
|
+
* @param name The name of the property to access.
|
18
|
+
*/
|
19
|
+
public JSValue(PluginCall call, String name) {
|
20
|
+
this.value = this.toValue(call, name);
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Returns the coerced but uncasted underlying value.
|
25
|
+
*/
|
26
|
+
public Object getValue() {
|
27
|
+
return this.value;
|
28
|
+
}
|
29
|
+
|
30
|
+
@Override
|
31
|
+
public String toString() {
|
32
|
+
return this.getValue().toString();
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Returns the underlying value as a JSObject, or throwing if it cannot.
|
37
|
+
*
|
38
|
+
* @throws JSONException If the underlying value is not a JSObject.
|
39
|
+
*/
|
40
|
+
public JSObject toJSObject() throws JSONException {
|
41
|
+
if (this.value instanceof JSObject) return (JSObject) this.value;
|
42
|
+
throw new JSONException("JSValue could not be coerced to JSObject.");
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Returns the underlying value as a JSArray, or throwing if it cannot.
|
47
|
+
*
|
48
|
+
* @throws JSONException If the underlying value is not a JSArray.
|
49
|
+
*/
|
50
|
+
public JSArray toJSArray() throws JSONException {
|
51
|
+
if (this.value instanceof JSArray) return (JSArray) this.value;
|
52
|
+
throw new JSONException("JSValue could not be coerced to JSArray.");
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Returns the underlying value this object represents, coercing it into a capacitor-friendly object if supported.
|
57
|
+
*/
|
58
|
+
private Object toValue(PluginCall call, String name) {
|
59
|
+
Object value = null;
|
60
|
+
value = call.getArray(name, null);
|
61
|
+
if (value != null) return value;
|
62
|
+
value = call.getObject(name, null);
|
63
|
+
if (value != null) return value;
|
64
|
+
value = call.getString(name, null);
|
65
|
+
if (value != null) return value;
|
66
|
+
return call.getData().opt(name);
|
67
|
+
}
|
68
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
package org.thiragatisoft.core.http;
|
2
|
+
|
3
|
+
enum MimeType {
|
4
|
+
APPLICATION_JSON("application/json"),
|
5
|
+
APPLICATION_VND_API_JSON("application/vnd.api+json"), // https://jsonapi.org
|
6
|
+
TEXT_HTML("text/html");
|
7
|
+
|
8
|
+
private final String value;
|
9
|
+
|
10
|
+
MimeType(String value) {
|
11
|
+
this.value = value;
|
12
|
+
}
|
13
|
+
|
14
|
+
String getValue() {
|
15
|
+
return value;
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<module type="JAVA_MODULE" version="4">
|
3
|
+
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
4
|
+
<exclude-output />
|
5
|
+
<content url="file://$MODULE_DIR$">
|
6
|
+
<sourceFolder url="file://$MODULE_DIR$/java" isTestSource="false" />
|
7
|
+
</content>
|
8
|
+
<orderEntry type="inheritedJdk" />
|
9
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
10
|
+
<orderEntry type="module" module-name="test" />
|
11
|
+
</component>
|
12
|
+
</module>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
package com.getcapacitor;
|
2
|
+
|
3
|
+
import org.junit.Test;
|
4
|
+
|
5
|
+
import static org.junit.Assert.*;
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Example local unit test, which will execute on the development machine (host).
|
9
|
+
*
|
10
|
+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
11
|
+
*/
|
12
|
+
public class ExampleUnitTest {
|
13
|
+
@Test
|
14
|
+
public void addition_isCorrect() throws Exception {
|
15
|
+
assertEquals(4, 2 + 2);
|
16
|
+
}
|
17
|
+
}
|