11#!/usr/bin/env python
22import io
3+ import re
34import zipfile
45from datetime import datetime
56from itertools import tee
@@ -252,8 +253,39 @@ def size(self):
252253 return self .fp ._file_size if self .fp else 0
253254
254255
255- def _list_files (url , support_suffix_range , filenames ):
256- with RemoteZip (url , headers = {'User-Agent' : 'remotezip' }, support_suffix_range = support_suffix_range ) as zip :
256+ _header_re = re .compile (r'\A\s*([^\s:]+)\s*:\s?(.*?)\Z' )
257+
258+
259+ def _build_headers (headers ):
260+ """
261+ Build requests-compatible headers dict from command line argument values.
262+ """
263+ # Combine multiple headers with the same name into a
264+ # comma-separated single value. This is equivalent in HTTP
265+ # (according to RFC 9110 section 5.2), and requests wants the
266+ # headers in a dict.
267+ headers_dict = requests .utils .CaseInsensitiveDict ()
268+ for header in headers :
269+ m = _header_re .match (header )
270+ if not m :
271+ raise ValueError (f'Invalid HTTP request header: { header !r} ' )
272+ if m [1 ] in headers_dict :
273+ headers_dict [m [1 ]] += f', { m [2 ]} '
274+ else :
275+ headers_dict [m [1 ]] = m [2 ]
276+
277+ if 'user-agent' not in headers_dict :
278+ headers_dict ['User-Agent' ] = 'remotezip'
279+
280+ return headers_dict
281+
282+
283+ def _list_files (url , support_suffix_range , filenames , headers ):
284+ with RemoteZip (
285+ url ,
286+ headers = _build_headers (headers ),
287+ support_suffix_range = support_suffix_range ,
288+ ) as zip :
257289 if len (filenames ) == 0 :
258290 filenames = zip .namelist ()
259291 data = []
@@ -279,8 +311,12 @@ def _printTable(data, header, align):
279311 print ()
280312
281313
282- def _extract_files (url , support_suffix_range , filenames , path ):
283- with RemoteZip (url , support_suffix_range = support_suffix_range ) as zip :
314+ def _extract_files (url , support_suffix_range , filenames , path , headers ):
315+ with RemoteZip (
316+ url ,
317+ headers = _build_headers (headers ),
318+ support_suffix_range = support_suffix_range ,
319+ ) as zip :
284320 if len (filenames ) == 0 :
285321 filenames = zip .namelist ()
286322 for fname in filenames :
@@ -298,13 +334,16 @@ def main():
298334 parser .add_argument ('-l' , '--list' , action = 'store_true' , help = 'List files in the archive' )
299335 parser .add_argument ('-d' , '--dir' , default = os .getcwd (), help = 'Extract directory, default current directory' )
300336 parser .add_argument ('--disable-suffix-range-support' , action = 'store_true' , help = 'Use when remote server does not support suffix range (negative offset)' )
337+ parser .add_argument ('-H' , '--header' , action = 'append' , default = [], metavar = 'NAME:VALUE' , help = 'HTTP request header' )
301338
302339 args = parser .parse_args ()
303340 support_suffix_range = not args .disable_suffix_range_support
304341 if args .list :
305- _list_files (args .url , support_suffix_range , args .filename )
342+ _list_files (args .url , support_suffix_range , args .filename , args . header )
306343 else :
307- _extract_files (args .url , support_suffix_range , args .filename , args .dir )
344+ _extract_files (
345+ args .url , support_suffix_range , args .filename , args .dir ,
346+ args .header )
308347
309348
310349if __name__ == "__main__" :
0 commit comments