11// Copyright (c) Microsoft Corporation. All rights reserved.
22// Licensed under the MIT License.
33
4- using Microsoft . PowerShell . PSResourceGet . UtilClasses ;
54using System ;
65using System . Collections ;
76using System . Collections . Generic ;
7+ using System . Collections . ObjectModel ;
88using System . IO ;
9- using System . Net . Http ;
10- using NuGet . Versioning ;
11- using System . Threading . Tasks ;
12- using System . Net ;
9+ using System . Linq ;
1310using System . Management . Automation ;
14- using Newtonsoft . Json . Linq ;
15- using Newtonsoft . Json ;
16- using System . Collections . ObjectModel ;
11+ using System . Net ;
12+ using System . Net . Http ;
1713using System . Net . Http . Headers ;
18- using System . Linq ;
19- using Microsoft . PowerShell . PSResourceGet . Cmdlets ;
20- using System . Text ;
2114using System . Security . Cryptography ;
15+ using System . Text ;
2216using System . Text . Json ;
17+ using System . Text . RegularExpressions ;
18+ using System . Threading . Tasks ;
19+ using Microsoft . PowerShell . PSResourceGet . Cmdlets ;
20+ using Microsoft . PowerShell . PSResourceGet . UtilClasses ;
21+ using Newtonsoft . Json ;
22+ using Newtonsoft . Json . Linq ;
23+ using NuGet . Versioning ;
2324
2425namespace Microsoft . PowerShell . PSResourceGet
2526{
@@ -688,7 +689,7 @@ internal JObject FindAllRepositories(string containerRegistryAccessToken, out Er
688689 _cmdletPassedIn . WriteDebug ( "In ContainerRegistryServerAPICalls::FindAllRepositories()" ) ;
689690 string repositoryListUrl = string . Format ( containerRegistryRepositoryListTemplate , Registry ) ;
690691 var defaultHeaders = GetDefaultHeaders ( containerRegistryAccessToken ) ;
691- return GetHttpResponseJObjectUsingDefaultHeaders ( repositoryListUrl , HttpMethod . Get , defaultHeaders , out errRecord ) ;
692+ return GetHttpResponseJObjectUsingDefaultHeaders ( repositoryListUrl , HttpMethod . Get , defaultHeaders , out errRecord , usePagination : true ) ;
692693 }
693694
694695 /// <summary>
@@ -937,7 +938,7 @@ internal async Task<HttpContent> GetHttpContentResponseJObject(string url, Colle
937938 /// <summary>
938939 /// Get response object when using default headers in the request.
939940 /// </summary>
940- internal JObject GetHttpResponseJObjectUsingDefaultHeaders ( string url , HttpMethod method , Collection < KeyValuePair < string , string > > defaultHeaders , out ErrorRecord errRecord )
941+ internal JObject GetHttpResponseJObjectUsingDefaultHeaders ( string url , HttpMethod method , Collection < KeyValuePair < string , string > > defaultHeaders , out ErrorRecord errRecord , bool usePagination = false )
941942 {
942943 _cmdletPassedIn . WriteDebug ( "In ContainerRegistryServerAPICalls::GetHttpResponseJObjectUsingDefaultHeaders()" ) ;
943944 try
@@ -946,7 +947,8 @@ internal JObject GetHttpResponseJObjectUsingDefaultHeaders(string url, HttpMetho
946947 HttpRequestMessage request = new HttpRequestMessage ( method , url ) ;
947948 SetDefaultHeaders ( defaultHeaders ) ;
948949
949- return SendRequestAsync ( request ) . GetAwaiter ( ) . GetResult ( ) ;
950+ var response = usePagination ? SendRequestAsyncWithPagination ( request ) : SendRequestAsync ( request ) ;
951+ return response . GetAwaiter ( ) . GetResult ( ) ;
950952 }
951953 catch ( ResourceNotFoundException e )
952954 {
@@ -1152,6 +1154,63 @@ private async Task<JObject> SendRequestAsync(HttpRequestMessage message)
11521154 return JsonConvert . DeserializeObject < JObject > ( await response . Content . ReadAsStringAsync ( ) ) ;
11531155 }
11541156
1157+ private async Task < JObject > SendRequestAsyncWithPagination ( HttpRequestMessage initialMessage )
1158+ {
1159+ HttpResponseMessage response ;
1160+ string nextUrl = initialMessage . RequestUri . ToString ( ) ;
1161+ JObject finalResult = new JObject ( ) ;
1162+ JArray allRepositories = new JArray ( ) ;
1163+
1164+ do
1165+ {
1166+ var message = new HttpRequestMessage ( HttpMethod . Get , nextUrl ) ;
1167+ try
1168+ {
1169+ response = await _sessionClient . SendAsync ( message ) ;
1170+ }
1171+ catch ( Exception e )
1172+ {
1173+ throw new SendRequestException ( $ "Error occurred while sending request to Container Registry server with: { e . GetType ( ) } '{ e . Message } '", e ) ;
1174+ }
1175+
1176+ switch ( response . StatusCode )
1177+ {
1178+ case HttpStatusCode . OK :
1179+ break ;
1180+ case HttpStatusCode . Unauthorized :
1181+ throw new UnauthorizedException ( $ "Response returned status code: { response . ReasonPhrase } .") ;
1182+ case HttpStatusCode . NotFound :
1183+ throw new ResourceNotFoundException ( $ "Response returned status code package: { response . ReasonPhrase } .") ;
1184+ default :
1185+ throw new Exception ( $ "Response returned error with status code { response . StatusCode } : { response . ReasonPhrase } .") ;
1186+ }
1187+
1188+ var content = await response . Content . ReadAsStringAsync ( ) ;
1189+ var json = JObject . Parse ( content ) ;
1190+ var repositories = json [ "repositories" ] as JArray ;
1191+ if ( repositories != null )
1192+ {
1193+ allRepositories . Merge ( repositories ) ;
1194+ }
1195+
1196+ // Check for Link header to continue pagination
1197+ if ( response . Headers . TryGetValues ( "Link" , out var linkHeaders ) )
1198+ {
1199+ var linkHeader = string . Join ( "," , linkHeaders ) ;
1200+ var match = Regex . Match ( linkHeader , @"<([^>]+)>;\s*rel=""next""" ) ;
1201+ nextUrl = match . Success ? match . Groups [ 1 ] . Value : null ;
1202+ }
1203+ else
1204+ {
1205+ nextUrl = null ;
1206+ }
1207+
1208+ } while ( ! string . IsNullOrEmpty ( nextUrl ) ) ;
1209+
1210+ finalResult [ "repositories" ] = allRepositories ;
1211+ return finalResult ;
1212+ }
1213+
11551214 /// <summary>
11561215 /// Send request to get response headers.
11571216 /// </summary>
0 commit comments