@@ -530,32 +530,45 @@ def read_with_paging(subpath, query = nil, iteration: nil, **call_args)
530530 Aspera . assert_type ( query , Hash , NilClass ) { 'query' }
531531 Aspera . assert ( !call_args . key? ( :query ) )
532532 query = { } if query . nil?
533- query [ :iteration_token ] = iteration [ 0 ] unless iteration . nil?
533+ query [ :iteration_token ] = iteration [ 0 ] unless iteration . nil? || iteration [ 0 ] . nil?
534534 max = query . delete ( RestList ::MAX_ITEMS )
535+ # Return empty list immediately if max is 0
536+ return [ ] if max &.zero?
535537 item_list = [ ]
536538 loop do
537539 data , http = read ( subpath , query , **call_args , ret : :both )
538540 Aspera . assert_type ( data , Array ) { "Expected data to be an Array, got: #{ data . class } " }
539541 # no data
540542 break if data . empty?
541- # get next iteration token from link
542- next_iteration_token = nil
543- link_info = http [ 'Link' ]
544- unless link_info . nil?
545- m = link_info . match ( /<([^>]+)>/ )
546- Aspera . assert ( m ) { "Cannot parse iteration in Link: #{ link_info } " }
547- next_iteration_token = Rest . query_to_h ( URI . parse ( m [ 1 ] ) . query ) [ 'iteration_token' ]
548- end
549- # same as last iteration: stop
550- break if next_iteration_token &.eql? ( query [ :iteration_token ] )
551- query [ :iteration_token ] = next_iteration_token
552543 item_list . concat ( data )
544+ # Check if we reached the max limit
553545 if max &.<=( item_list . length )
554546 item_list = item_list . slice ( 0 , max )
555547 break
556548 end
549+ # Update progress spinner
550+ RestParameters . instance . spinner_cb . call ( item_list . length )
551+ # Parse Link header according to RFC 8288 to extract next iteration token
552+ next_url = Rest . parse_link_header ( http [ 'Link' ] , rel : 'next' )
553+ next_iteration_token = nil
554+ if next_url
555+ begin
556+ parsed_uri = URI . parse ( next_url )
557+ query_params = Rest . query_to_h ( parsed_uri . query ) if parsed_uri . query
558+ next_iteration_token = query_params [ 'iteration_token' ] if query_params
559+ rescue URI ::InvalidURIError => e
560+ Log . log . warn { "Invalid URI in Link header: #{ next_url } - #{ e . message } " }
561+ end
562+ end
563+ # Stop if no next token
557564 break if next_iteration_token . nil?
565+ # Stop if same token as current (infinite loop protection)
566+ break if next_iteration_token . eql? ( query [ :iteration_token ] )
567+ # Update token for next iteration
568+ query [ :iteration_token ] = next_iteration_token
558569 end
570+ # Signal completion
571+ RestParameters . instance . spinner_cb . call ( action : :success )
559572 # save iteration token if needed
560573 iteration [ 0 ] = query [ :iteration_token ] unless iteration . nil?
561574 item_list
0 commit comments