Skip to content

Commit

Permalink
Merge pull request #215 from chrisws/master
Browse files Browse the repository at this point in the history
Tidy up request implementation
  • Loading branch information
chrisws authored Apr 26, 2024
2 parents 2aed92b + 02a01e5 commit 84c2246
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/platform/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ android {
applicationId 'net.sourceforge.smallbasic'
minSdkVersion 19
targetSdkVersion 34
versionCode 61
versionCode 63
versionName '12.27'
resourceConfigurations += ['en']
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package net.sourceforge.smallbasic;

import androidx.annotation.NonNull;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class HttpConnection implements Runnable {
private static final int TIMEOUT_MILLIS = 30000;
private static final String ERROR_PREFIX = "error: [";
private static final String ERROR_POSTFIX = "]";

private final String endPoint;
private final String data;
private final String apiKey;
private final CountDownLatch latch;
private String result;

public HttpConnection(String endPoint, String data, String apiKey) {
this.endPoint = endPoint;
this.data = data;
this.apiKey = apiKey;
this.latch = new CountDownLatch(1);
}

public String invoke() {
new Thread(this).start();
try {
if (!latch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
result = buildError("timeout");
}
} catch (InterruptedException e) {
result = buildError(e.toString());
}
return result;
}

@Override
public void run() {
HttpURLConnection conn = null;
try {
conn = getHttpURLConnection(endPoint, (data == null || data.isEmpty()) ? "GET" : "POST", apiKey);
if (data != null && !data.isEmpty()) {
conn.setRequestProperty("Content-Length", "" + data.getBytes().length);
conn.setDoInput(true);
OutputStream os = conn.getOutputStream();
os.write(data.getBytes(StandardCharsets.UTF_8));
os.flush();
os.close();
}
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
result = getText(conn.getInputStream());
} else if (responseCode >= HttpURLConnection.HTTP_BAD_REQUEST && responseCode < HttpURLConnection.HTTP_INTERNAL_ERROR) {
result = buildError(getText(conn.getErrorStream()));
} else {
result = buildError(String.valueOf(responseCode));
}
} catch (Exception e) {
result = buildError(e.toString());
} finally {
if (conn != null) {
conn.disconnect();
}
}
latch.countDown();
}

@NonNull
private static String buildError(String message) {
return ERROR_PREFIX + message + ERROR_POSTFIX;
}

@NonNull
private HttpURLConnection getHttpURLConnection(String endPoint, String method, String apiKey) throws IOException {
URL url = new URL(endPoint);
HttpURLConnection result = (HttpURLConnection) url.openConnection();
result.setRequestMethod(method);
result.setRequestProperty("User-Agent", "SmallBASIC");
result.setConnectTimeout(TIMEOUT_MILLIS);
result.setInstanceFollowRedirects(true);
if (apiKey != null && !apiKey.isEmpty()) {
result.setRequestProperty("Accept", "application/json");
result.setRequestProperty("Content-Type", "application/json");
result.setRequestProperty("Authorization", "Bearer " + apiKey);
} else {
result.setRequestProperty("Accept", "*/*");
}
return result;
}

private String getText(InputStream stream) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
Expand All @@ -59,14 +58,11 @@
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
Expand Down Expand Up @@ -103,7 +99,6 @@ public class MainActivity extends NativeActivity {
private static final String FOLDER_NAME = "SmallBASIC";
private static final int COPY_BUFFER_SIZE = 1024;
private static final String[] SAMPLES = {"welcome.bas"};
private static final int TIMEOUT_MILLIS = 5000;
private String _startupBas = null;
private boolean _untrusted = false;
private final ExecutorService _audioExecutor = Executors.newSingleThreadExecutor();
Expand Down Expand Up @@ -510,33 +505,8 @@ public boolean removeLocationUpdates() {
}

public String request(String endPoint, String data, String apiKey) throws IOException {
String result;
try {
HttpURLConnection conn = getHttpURLConnection(endPoint, (data == null || data.isEmpty()) ? "GET" : "POST", apiKey);
if (data != null && !data.isEmpty()) {
conn.setRequestProperty("Content-Length", "" + data.getBytes().length);
OutputStream os = conn.getOutputStream();
os.write(data.getBytes(StandardCharsets.UTF_8));
os.flush();
os.close();
}
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
result = response.toString();
} else {
result = "error: [" + responseCode + "]";
}
} catch (Exception e) {
result = "error: [" + e + "]";
}
return result;
HttpConnection connection = new HttpConnection(endPoint, data, apiKey);
return connection.invoke();
}

public boolean requestLocationUpdates() {
Expand Down Expand Up @@ -798,23 +768,6 @@ private void execStream(InputStream inputStream) throws IOException {
runFile(outputFile.getAbsolutePath());
}

@NonNull
private HttpURLConnection getHttpURLConnection(String endPoint, String method, String apiKey) throws IOException {
URL url = new URL(endPoint);
HttpURLConnection result = (HttpURLConnection) url.openConnection();
result.setConnectTimeout(TIMEOUT_MILLIS);
result.setRequestProperty("User-Agent", "SmallBASIC");
result.setRequestMethod(method);
result.setInstanceFollowRedirects(true);
if (apiKey != null && !apiKey.isEmpty()) {
result.setRequestProperty("Accept", "application/json");
result.setRequestProperty("Content-Type", "application/json");
result.setRequestProperty("Authorization", "Bearer " + apiKey);
}
result.setDoOutput(true);
return result;
}

private Uri getSharedFile(File file) {
Uri result;
try {
Expand Down
13 changes: 9 additions & 4 deletions src/platform/android/jni/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,8 +977,15 @@ int Runtime::getFontId() {

int Runtime::invokeRequest(int argc, slib_par_t *params, var_t *retval) {
int result = 0;
if ((argc >= 1 && argc <= 3 && v_is_type(params[0].var_p, V_STR)) &&
(argc < 3 || v_is_type(params[2].var_p, V_STR))) {
if (argc != 1 && argc != 3) {
v_setstr(retval, "Expected 1 or 3 arguments");
} else if (!v_is_type(params[0].var_p, V_STR)) {
v_setstr(retval, "invalid endPoint");
} else if (argc == 3 && !v_is_type(params[1].var_p, V_STR) && !v_is_type(params[1].var_p, V_MAP)) {
v_setstr(retval, "invalid postData");
} else if (argc == 3 && !v_is_type(params[2].var_p, V_STR)) {
v_setstr(retval, "invalid apiKey");
} else {
_output->redraw();

JNIEnv *env;
Expand All @@ -1002,8 +1009,6 @@ int Runtime::invokeRequest(int argc, slib_par_t *params, var_t *retval) {
env->DeleteLocalRef(apiKey);

_app->activity->vm->DetachCurrentThread();
} else {
v_setstr(retval, "Invalid request arguments");
}
return result;
}
Expand Down

0 comments on commit 84c2246

Please sign in to comment.