Invoke-WebRequest in a loop until NotFound I'm using SAP's Raylight RESTful SDK to get a list of universes from the BusinessObject Enterprise repository.

To get all of the universes, the request needs to be called repeatedly, incrementing the offset parameter until the request returns a Not Found [404] error.

Current approach:

$baseUrl = 'http://&lt;server&gt;:6405/biprws/raylight/v1'

$headers = @{}
$headers.Add("Accept", "application/json")
$headers.Add("Content-Type", "application/json")
$headers.Add("x-sap-logontoken", $Token)

$offset = 0
$limit = 50

try {
    do {

        $Path = "/universes?offset=$offset&amp;limit=$limit"

        $response = Invoke-WebRequest "$baseUrl$Path" -Headers $headers 
        ($response | ConvertFrom-Json).universes.universe

        $offset += $limit

    } until ( $response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound )
}
catch {
    # catches 404 too
    Write-Debug "StatusCode: $($_.Exception.Response.StatusCode.Value__)"
}


While the code returns the expected results, I not sure that I like how the code will always exit via the catch.  I could remove the try/catch, but that will leave the code exposed to other errors.

Is there a way to improve this?
You appear to have some incorrect logic. The until expression will never get evaluated in the case of a 404 exception. It will get skipped over. So it's kind of pointless.

So let's replace the repeat ... until with a while ($true). That is, an infinite loop. This works the same as what you already had, but the logic is clearer. I added a comment at the top, too, to let the reader know that a 404 exception will break the loop:

while ($true) {
    # Will throw 404 exception when finished.

    $Path = "/universes?offset=$offset&amp;limit=$limit"

    $response = Invoke-WebRequest "$baseUrl$Path" -Headers $headers 
    ($response | ConvertFrom-Json).universes.universe

    $offset += $limit
}


Now, in general it's not good to use exceptions for normal program control flow. They should normally be used for exceptional cases only. But sometimes—such as in this case it would seem—we do have to use them. In such cases the usual pattern is to catch the exception and then examine it to see if it's a normal control flow exception or if it's a true exception, and respond accordingly.

So let's do that. If we catch a 404 exception, then we will just ignore it. If it's anything else, then we will rethrow it:

try {
    while ($true) {
        # Will throw 404 exception when finished.

        $Path = "/universes?offset=$offset&amp;limit=$limit"

        $response = Invoke-WebRequest "$baseUrl$Path" -Headers $headers 
        ($response | ConvertFrom-Json).universes.universe

        $offset += $limit
    }
}
catch [System.Net.WebException] {
    $statusCode = $_.Exception.Response.StatusCode.Value__

    if ($statusCode -eq 404) {
        # Normal end case. Do nothing.
    }
    else {
        throw
    }
}