2626 from urllib .error import HTTPError , URLError
2727 from urllib .request import urlopen
2828 from urllib .request import Request
29+ from urllib .request import HTTPRedirectHandler
30+ from urllib .request import build_opener
2931except ImportError :
3032 # python 2
3133 from urlparse import urlparse
@@ -34,6 +36,8 @@ except ImportError:
3436 from urllib2 import HTTPError , URLError
3537 from urllib2 import urlopen
3638 from urllib2 import Request
39+ from urllib2 import HTTPRedirectHandler
40+ from urllib2 import build_opener
3741
3842from github_backup import __version__
3943
@@ -537,22 +541,33 @@ def _request_url_error(template, retry_timeout):
537541 return False
538542
539543
544+ class S3HTTPRedirectHandler (HTTPRedirectHandler ):
545+ """
546+ A subclassed redirect handler for downloading Github assets from S3.
547+
548+ urllib will add the Authorization header to the redirected request to S3, which will result in a 400,
549+ so we should remove said header on redirect.
550+ """
551+ def redirect_request (self , req , fp , code , msg , headers , newurl ):
552+ request = super (S3HTTPRedirectHandler , self ).redirect_request (req , fp , code , msg , headers , newurl )
553+ del request .headers ['Authorization' ]
554+ return request
555+
556+
540557def download_file (url , path , auth ):
541558 request = Request (url )
542559 request .add_header ('Accept' , 'application/octet-stream' )
543560 request .add_header ('Authorization' , 'Basic ' .encode ('ascii' ) + auth )
544- data = urlopen (request )
561+ opener = build_opener (S3HTTPRedirectHandler )
562+ response = opener .open (request )
563+
564+ chunk_size = 16 * 1024
545565 with open (path , 'wb' ) as f :
546- f .write (data .read ())
547-
548- # import requests
549- # r = requests.get(url, stream=True, headers={
550- # 'Accept': 'application/octet-stream',
551- # 'Authorization': 'Basic '.encode('ascii') + auth
552- # })
553- # with open(path, 'wb') as f:
554- # for chunk in r.iter_content(1024):
555- # f.write(chunk)
566+ while True :
567+ chunk = response .read (chunk_size )
568+ if not chunk :
569+ break
570+ f .write (chunk )
556571
557572
558573def get_authenticated_user (args ):
0 commit comments