Skip to content

Change Binary Download Distribution #93

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/com/browserstack/local/Local.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public void start(Map<String, String> options) throws Exception {
startOptions = options;
LocalBinary lb;
if (options.get("binarypath") != null) {
lb = new LocalBinary(options.get("binarypath"));
lb = new LocalBinary(options.get("binarypath"), options.get("key"));
} else {
lb = new LocalBinary("");
lb = new LocalBinary("", options.get("key"));
}
binaryPath = lb.getBinaryPath();

Expand Down
84 changes: 73 additions & 11 deletions src/main/java/com/browserstack/local/LocalBinary.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.File;
Expand All @@ -15,14 +18,24 @@
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipException;

import java.lang.StringBuilder;

class LocalBinary {

private static final String BIN_URL = "https://www.browserstack.com/local-testing/downloads/binaries/";

private String httpPath;
private String binaryFileName;

private String sourceUrl;

private String binaryPath;

private Boolean fallbackEnabled = false;

private Throwable downloadFailureThrowable = null;

private String key;

private boolean isOSWindows;

private final String orderedPaths[] = {
Expand All @@ -31,14 +44,26 @@ class LocalBinary {
System.getProperty("java.io.tmpdir")
};

LocalBinary(String path) throws LocalException {
LocalBinary(String path, String key) throws LocalException {
this.key = key;
initialize();
if (path != "") {
getBinaryOnPath(path);
} else {
getBinary();
downloadAndVerifyBinary(path);
}

private void downloadAndVerifyBinary(String path) throws LocalException {
try {
if (path != "") {
getBinaryOnPath(path);
} else {
getBinary();
}
checkBinary();
} catch (Throwable e) {
if (fallbackEnabled) throw e;
fallbackEnabled = true;
downloadFailureThrowable = e;
downloadAndVerifyBinary(path);
}
checkBinary();
}

private void initialize() throws LocalException {
Expand All @@ -65,8 +90,7 @@ private void initialize() throws LocalException {
throw new LocalException("Failed to detect OS type");
}

String sourceURL = BIN_URL;
httpPath = sourceURL + binFileName;
this.binaryFileName = binFileName;
}

private boolean isAlpine() {
Expand Down Expand Up @@ -167,8 +191,46 @@ private boolean makePath(String path) {
}
}

private void fetchSourceUrl() {
if ((!fallbackEnabled && sourceUrl) || (fallbackEnabled && !downloadFailureThrowable)) {
/* Retry because binary (from any of the endpoints) validation failed */
return;
}

URL url = new URL("https://local.browserstack.com/binary/api/v1/endpoint");
URLConnection connection = url.openConnection();

connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("User-Agent", "browserstack-local-java/" + Local.getPackageVersion());
connection.setRequestProperty("Accept", "application/json");
if (fallbackEnabled) connection.setRequestProperty("X-Local-Fallback-Cloudflare", "true");

String jsonInput = "{\"auth_token\": " + key + (fallbackEnabled ? (", \"error_message\": " + downloadFailureThrowable.getMessage()) : "") + "}";

try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonInput.getBytes("utf-8");
os.write(input, 0, input.length);
}

try (InputStream is = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line.trim());
}
String responseBody = response.toString();
JSONObject json = new JSONObject(responseBody);
this.sourceUrl = json.getJSONObject("data").getString("endpoint");
if(fallbackEnabled) downloadFailureThrowable = null;
}
}

private void downloadBinary(String destParentDir, Boolean custom) throws LocalException {
try {
fetchSourceUrl();

String source = destParentDir;
if (!custom) {
if (!new File(destParentDir).exists())
Expand All @@ -179,13 +241,13 @@ private void downloadBinary(String destParentDir, Boolean custom) throws LocalEx
source += ".exe";
}
}
URL url = new URL(httpPath);
URL url = new URL(sourceUrl + '/' + binaryFileName);

File f = new File(source);
newCopyToFile(url, f);

changePermissions(binaryPath);
} catch (Exception e) {
} catch (Throwable e) {
throw new LocalException("Error trying to download BrowserStackLocal binary: " + e.getMessage());
}
}
Expand Down