1
1
// Copyright (c) Microsoft Corporation. All rights reserved.
2
2
// Licensed under the MIT License.
3
3
4
- using Microsoft . PowerShell . PSResourceGet . UtilClasses ;
5
4
using System ;
6
5
using System . Collections ;
7
6
using System . Collections . Generic ;
7
+ using System . Collections . ObjectModel ;
8
8
using System . IO ;
9
- using System . Net . Http ;
10
- using NuGet . Versioning ;
11
- using System . Threading . Tasks ;
12
- using System . Net ;
9
+ using System . Linq ;
13
10
using 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 ;
17
13
using System . Net . Http . Headers ;
18
- using System . Linq ;
19
- using Microsoft . PowerShell . PSResourceGet . Cmdlets ;
20
- using System . Text ;
21
14
using System . Security . Cryptography ;
15
+ using System . Text ;
22
16
using 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 ;
23
24
24
25
namespace Microsoft . PowerShell . PSResourceGet
25
26
{
@@ -688,7 +689,7 @@ internal JObject FindAllRepositories(string containerRegistryAccessToken, out Er
688
689
_cmdletPassedIn . WriteDebug ( "In ContainerRegistryServerAPICalls::FindAllRepositories()" ) ;
689
690
string repositoryListUrl = string . Format ( containerRegistryRepositoryListTemplate , Registry ) ;
690
691
var defaultHeaders = GetDefaultHeaders ( containerRegistryAccessToken ) ;
691
- return GetHttpResponseJObjectUsingDefaultHeaders ( repositoryListUrl , HttpMethod . Get , defaultHeaders , out errRecord ) ;
692
+ return GetHttpResponseJObjectUsingDefaultHeaders ( repositoryListUrl , HttpMethod . Get , defaultHeaders , out errRecord , usePagination : true ) ;
692
693
}
693
694
694
695
/// <summary>
@@ -937,7 +938,7 @@ internal async Task<HttpContent> GetHttpContentResponseJObject(string url, Colle
937
938
/// <summary>
938
939
/// Get response object when using default headers in the request.
939
940
/// </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 )
941
942
{
942
943
_cmdletPassedIn . WriteDebug ( "In ContainerRegistryServerAPICalls::GetHttpResponseJObjectUsingDefaultHeaders()" ) ;
943
944
try
@@ -946,7 +947,8 @@ internal JObject GetHttpResponseJObjectUsingDefaultHeaders(string url, HttpMetho
946
947
HttpRequestMessage request = new HttpRequestMessage ( method , url ) ;
947
948
SetDefaultHeaders ( defaultHeaders ) ;
948
949
949
- return SendRequestAsync ( request ) . GetAwaiter ( ) . GetResult ( ) ;
950
+ var response = usePagination ? SendRequestAsyncWithPagination ( request ) : SendRequestAsync ( request ) ;
951
+ return response . GetAwaiter ( ) . GetResult ( ) ;
950
952
}
951
953
catch ( ResourceNotFoundException e )
952
954
{
@@ -1152,6 +1154,72 @@ private async Task<JObject> SendRequestAsync(HttpRequestMessage message)
1152
1154
return JsonConvert . DeserializeObject < JObject > ( await response . Content . ReadAsStringAsync ( ) ) ;
1153
1155
}
1154
1156
1157
+ private async Task < JObject > SendRequestAsyncWithPagination ( HttpRequestMessage initialMessage )
1158
+ {
1159
+ HttpResponseMessage response ;
1160
+ string nextUrl = initialMessage . RequestUri . ToString ( ) ;
1161
+ string urlBase = initialMessage . RequestUri . Scheme + "://" + initialMessage . RequestUri . Host ;
1162
+ JObject finalResult = new JObject ( ) ;
1163
+ JArray allRepositories = new JArray ( ) ;
1164
+
1165
+ do
1166
+ {
1167
+ var message = new HttpRequestMessage ( HttpMethod . Get , nextUrl ) ;
1168
+ try
1169
+ {
1170
+ response = await _sessionClient . SendAsync ( message ) ;
1171
+ }
1172
+ catch ( Exception e )
1173
+ {
1174
+ throw new SendRequestException ( $ "Error occurred while sending request to Container Registry server with: { e . GetType ( ) } '{ e . Message } '", e ) ;
1175
+ }
1176
+
1177
+ switch ( response . StatusCode )
1178
+ {
1179
+ case HttpStatusCode . OK :
1180
+ break ;
1181
+ case HttpStatusCode . Unauthorized :
1182
+ throw new UnauthorizedException ( $ "Response returned status code: { response . ReasonPhrase } .") ;
1183
+ case HttpStatusCode . NotFound :
1184
+ throw new ResourceNotFoundException ( $ "Response returned status code package: { response . ReasonPhrase } .") ;
1185
+ default :
1186
+ throw new Exception ( $ "Response returned error with status code { response . StatusCode } : { response . ReasonPhrase } .") ;
1187
+ }
1188
+
1189
+ var content = await response . Content . ReadAsStringAsync ( ) ;
1190
+ var json = JObject . Parse ( content ) ;
1191
+ var repositories = json [ "repositories" ] as JArray ;
1192
+ if ( repositories != null )
1193
+ {
1194
+ allRepositories . Merge ( repositories ) ;
1195
+ }
1196
+
1197
+ // Check for Link header to continue pagination
1198
+ if ( response . Headers . TryGetValues ( "Link" , out var linkHeaders ) )
1199
+ {
1200
+ var linkHeader = string . Join ( "," , linkHeaders ) ;
1201
+ var match = Regex . Match ( linkHeader , @"<([^>]+)>;\s*rel=""next""" ) ;
1202
+ var nextUrlPart = match . Success ? match . Groups [ 1 ] . Value : null ;
1203
+ if ( ! string . IsNullOrEmpty ( nextUrlPart ) )
1204
+ {
1205
+ nextUrl = urlBase + nextUrlPart ;
1206
+ }
1207
+ else
1208
+ {
1209
+ nextUrl = null ;
1210
+ }
1211
+ }
1212
+ else
1213
+ {
1214
+ nextUrl = null ;
1215
+ }
1216
+
1217
+ } while ( ! string . IsNullOrEmpty ( nextUrl ) ) ;
1218
+
1219
+ finalResult [ "repositories" ] = allRepositories ;
1220
+ return finalResult ;
1221
+ }
1222
+
1155
1223
/// <summary>
1156
1224
/// Send request to get response headers.
1157
1225
/// </summary>
0 commit comments