11import platform , os , sys , stat , tempfile , re , subprocess
22from browserstack .bserrors import BrowserStackLocalError
33import gzip
4+ import json
45
56try :
67 from urllib .request import urlopen , Request
1011class LocalBinary :
1112 _version = None
1213
13- def __init__ (self ):
14+ def __init__ (self , key , error_object = None ):
15+ self .key = key
16+ self .error_object = error_object
1417 is_64bits = sys .maxsize > 2 ** 32
1518 self .is_windows = False
1619 osname = platform .system ()
17- source_url = "https://www.browserstack.com/local-testing/downloads/binaries/"
20+ source_url = self . fetch_source_url () + '/'
1821
1922 if osname == 'Darwin' :
2023 self .http_path = source_url + "BrowserStackLocal-darwin-x64"
@@ -37,6 +40,31 @@ def __init__(self):
3740 ]
3841 self .path_index = 0
3942
43+ def fetch_source_url (self ):
44+ url = "https://local.browserstack.com/binary/api/v1/endpoint"
45+ headers = {
46+ "Content-Type" : "application/json" ,
47+ "Accept" : "application/json"
48+ }
49+ data = {"auth_token" : self .key }
50+
51+ if self .error_object is not None :
52+ data ["error_message" ] = str (self .error_object )
53+ headers ["X-Local-Fallback-Cloudflare" ] = "true"
54+
55+ req = Request (url , data = json .dumps (data ).encode ("utf-8" ))
56+ for key , value in headers .items ():
57+ req .add_header (key , value )
58+
59+ try :
60+ with urlopen (req ) as response :
61+ resp_bytes = response .read ()
62+ resp_str = resp_bytes .decode ('utf-8' )
63+ resp_json = json .loads (resp_str )
64+ return resp_json ["data" ]["endpoint" ]
65+ except Exception as e :
66+ raise BrowserStackLocalError ('Error trying to fetch the source url for downloading the binary: {}' .format (e ))
67+
4068 @staticmethod
4169 def set_version (version ):
4270 LocalBinary ._version = version
@@ -61,7 +89,7 @@ def __available_dir(self):
6189 return final_path
6290 else :
6391 self .path_index += 1
64- raise BrowserStackLocalError ('Error trying to download BrowserStack Local binary' )
92+ raise BrowserStackLocalError ('Error trying to download BrowserStack Local binary, exhausted user directories to download to. ' )
6593
6694 def download (self , chunk_size = 8192 , progress_hook = None ):
6795 headers = {
@@ -80,6 +108,7 @@ def download(self, chunk_size=8192, progress_hook=None):
80108 total_size = int (response .info ().get_all ('Content-Length' )[0 ].strip () or '0' )
81109 bytes_so_far = 0
82110
111+ # Limits retries to the number of directories
83112 dest_parent_dir = self .__available_dir ()
84113 dest_binary_name = 'BrowserStackLocal'
85114 if self .is_windows :
0 commit comments