3
3
import org .apache .commons .io .FileUtils ;
4
4
import org .apache .commons .io .IOUtils ;
5
5
6
+ import org .json .JSONObject ;
7
+
6
8
import java .io .IOException ;
7
9
import java .io .InputStream ;
10
+ import java .io .OutputStream ;
8
11
import java .io .BufferedReader ;
9
12
import java .io .InputStreamReader ;
10
13
import java .io .File ;
15
18
import java .util .zip .GZIPInputStream ;
16
19
import java .util .zip .ZipException ;
17
20
21
+ import java .lang .StringBuilder ;
22
+
18
23
class LocalBinary {
19
24
20
25
private static final String BIN_URL = "https://www.browserstack.com/local-testing/downloads/binaries/" ;
21
26
22
- private String httpPath ;
27
+ private String binaryFileName ;
28
+
29
+ private String sourceUrl ;
23
30
24
31
private String binaryPath ;
25
32
33
+ private Boolean fallbackEnabled = false ;
34
+
35
+ private Throwable downloadFailureThrowable = null ;
36
+
37
+ private String key ;
38
+
26
39
private boolean isOSWindows ;
27
40
28
41
private final String orderedPaths [] = {
@@ -31,7 +44,8 @@ class LocalBinary {
31
44
System .getProperty ("java.io.tmpdir" )
32
45
};
33
46
34
- LocalBinary (String path ) throws LocalException {
47
+ LocalBinary (String path , String key ) throws LocalException {
48
+ this .key = key ;
35
49
initialize ();
36
50
if (path != "" ) {
37
51
getBinaryOnPath (path );
@@ -65,8 +79,7 @@ private void initialize() throws LocalException {
65
79
throw new LocalException ("Failed to detect OS type" );
66
80
}
67
81
68
- String sourceURL = BIN_URL ;
69
- httpPath = sourceURL + binFileName ;
82
+ this .binaryFileName = binFileName ;
70
83
}
71
84
72
85
private boolean isAlpine () {
@@ -167,8 +180,40 @@ private boolean makePath(String path) {
167
180
}
168
181
}
169
182
183
+ private void fetchSourceUrl () {
184
+ URL url = new URL ("https://local.browserstack.com/binary/api/v1/endpoint" );
185
+ URLConnection connection = url .openConnection ();
186
+
187
+ connection .setDoOutput (true );
188
+ connection .setRequestProperty ("Content-Type" , "application/json" );
189
+ connection .setRequestProperty ("User-Agent" , "browserstack-local-java/" + Local .getPackageVersion ());
190
+ connection .setRequestProperty ("Accept" , "application/json" );
191
+ if (fallbackEnabled ) connection .setRequestProperty ("X-Local-Fallback-Cloudflare" , "true" );
192
+
193
+ String jsonInput = "{\" auth_token\" : " + key + (fallbackEnabled ? (", \" error_message\" : " + downloadFailureThrowable .getMessage ()) : "" ) + "}" ;
194
+
195
+ try (OutputStream os = connection .getOutputStream ()) {
196
+ byte [] input = jsonInput .getBytes ("utf-8" );
197
+ os .write (input , 0 , input .length );
198
+ }
199
+
200
+ try (InputStream is = connection .getInputStream ();
201
+ BufferedReader reader = new BufferedReader (new InputStreamReader (is , "utf-8" ))) {
202
+ StringBuilder response = new StringBuilder ();
203
+ String line ;
204
+ while ((line = reader .readLine ()) != null ) {
205
+ response .append (line .trim ());
206
+ }
207
+ String responseBody = response .toString ();
208
+ JSONObject json = new JSONObject (responseBody );
209
+ this .sourceUrl = json .getJSONObject ("data" ).getString ("endpoint" );
210
+ }
211
+ }
212
+
170
213
private void downloadBinary (String destParentDir , Boolean custom ) throws LocalException {
171
214
try {
215
+ fetchSourceUrl ();
216
+
172
217
String source = destParentDir ;
173
218
if (!custom ) {
174
219
if (!new File (destParentDir ).exists ())
@@ -179,13 +224,20 @@ private void downloadBinary(String destParentDir, Boolean custom) throws LocalEx
179
224
source += ".exe" ;
180
225
}
181
226
}
182
- URL url = new URL (httpPath );
227
+ URL url = new URL (sourceUrl + '/' + binaryFileName );
183
228
184
229
File f = new File (source );
185
- newCopyToFile (url , f );
186
-
230
+ try {
231
+ newCopyToFile (url , f );
232
+ } catch (IOException e ) {
233
+ if (fallbackEnabled ) throw e ;
234
+ /* Binary download failed due to a server error */
235
+ fallbackEnabled = true ;
236
+ downloadFailureThrowable = e ;
237
+ downloadBinary (destParentDir , custom );
238
+ }
187
239
changePermissions (binaryPath );
188
- } catch (Exception e ) {
240
+ } catch (Throwable e ) {
189
241
throw new LocalException ("Error trying to download BrowserStackLocal binary: " + e .getMessage ());
190
242
}
191
243
}
0 commit comments