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,63 @@ 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
+ 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
+
1155
1214
/// <summary>
1156
1215
/// Send request to get response headers.
1157
1216
/// </summary>
0 commit comments