I've not played with SupportsPaging
before, so wanted to knock up some demo code & get feedback on whether my implementation is OK, or if I've misunderstood something. I created the function 'Invoke-DummyRestMethod' to simulate calling Invoke-RestMethod
with a URI for a web service which supported paging; only this Dummy version just spits out numbers, to keep things uncomplicated.
Function Invoke-DummyRestMethod {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]$Uri #= 'http://demo.com?start=20&limit=10' #example
)
begin {
[string]$regex = '(?:[\?&]limit=(?<limit>\d+)|[\?&]start=(?<start>\d+))+'
[long]$maxResults = 1000 #i.e. function will return 0 to 999 if no paging
}
Process {
[long]$start = 0 #nb: these must be declared as int; otherwise (as the results later come from a regex match) they'll be treated as strings / will cause issues with the Math.Min function!
[long]$limit = 0 #should 0 be a valid value / we use -1 for non valid? Assuming 0 is invalid
if ($Uri -match $regex) {
if($matches.start){$start = $matches.start}
if($matches.limit){$limit = $matches.limit}
}
write-verbose "Start: $start"
write-verbose "Limit: $limit"
if ($limit -le 0){$limit = $maxResults}
$start..([Math]::Min(($start+$limit),$maxResults) - 1)
}
}
Function Get-PagedData {
[CmdletBinding(SupportsPaging = $True)]
Param (
[parameter(Mandatory = $true)]
[uri]$Uri
)
Begin {
Add-Type -AssemblyName 'System' #NameValueCollection (ok, we don't need to add this type; but I like to be explicit)
Add-Type -AssemblyName 'System.Web' #HttpUtility
[long]$PagingSkip = [Math]::Max($PSCmdlet.PagingParameters.Skip,0)
[long]$PagingFirst = [Math]::Max($PSCmdlet.PagingParameters.First, 0)
}
Process {
[System.UriBuilder]$UriBuilder = New-Object -TypeName 'System.UriBuilder' -ArgumentList $Uri
[System.Collections.Specialized.NameValueCollection]$Query = [System.Web.HttpUtility]::ParseQueryString($UriBuilder.Query)
if ($PagingSkip -gt 0) {$Query['start'] = $PagingSkip}
if ($PagingFirst -gt 0) {$Query['limit'] = $PagingFirst}
$UriBuilder.Query = $Query.ToString()
Invoke-DummyRestMethod -Uri $UriBuilder.ToString() | Tee-Object -Variable 'Results'
}
End{
If ($PSCmdlet.PagingParameters.IncludeTotalCount){
[bool]$knownCount = ($PagingFirst -eq 0) -or ($PagingFirst -gt $Results.Count) #if we got less results than our limit (or we've not applied a limit) then we've reached the end, so we know the number of result
#$PSCmdlet.PagingParameters.NewTotalCount($Results.Count + $PagingSkip, 1.0 * $knownCount) #use this if we want to avoid estimates; i.e. if we don't have all the results, we don't have a clue how many there are
$PSCmdlet.PagingParameters.NewTotalCount($Results.Count + $PagingSkip, [Math]::Min(1.0, (1.0 * $knownCount + 0.5))) #use this if we want the number of results (plus any skipped) to be used as the estimated amount (i.e. there are at least this many results)
}
}
}
Get-PagedData 'http://demo.com' -Skip 10 -First 20 -IncludeTotalCount -Verbose
I'm particularly interested in the rules for estimation; i.e. where you know the exact number of items clearly the accuracy should be 1.0
; but where this figure's not known, is it OK to claim that because we have some results we can say that that's an estimate (since we know there are at least that many; so the total's not completely unknown); should we claim 0.0
as we don't know how far out this figure is, or is there some other guidance on this?
Related Gist: https://gist.github.com/JohnLBevan/70ee8247ae7c324f8710c8a8bedd2b96/