API response in case of exception
Hello,
I am making the following API request in Powershell:
$Result = Invoke-Restmethod -Uri "https://x.x.x.x:yyyyy/api/sonicos/address-objects/ipv4" -headers $headers -Body $jsonbody -Method POST.
If the request was successful, the variable $Result is filled, but if the request fails, $Result is empty.
Testing in Postman shows a filled response even if the request failed.
Can anyone tell me what I am doing wrong?
Kind regards
rainer
Best Answers
-
Jaime SonicWall Employee
Try using "-SkipHttpErrorCheck" in your Invoke-Restmethod call. It indeed seems to be a behavior of that cmdlet in PS. "-SkipHttpErrorCheck" ignores the "error statuses" non-200 response codes. Not sure exactly which codes it ignores. Maybe 4xx/5xx.
I found these that might be helpful.
2 -
Rainer Newbie ✭
Hi Jamie,
thanks, the second link provides the solution!
It explains the following:
"There is a known issue with PowerShell
Invoke-WebRequest
andInvoke-RestMethod
where the shell eats the response body when the status code is an error (4xx or 5xx). "And also provides the solution:
"You can fetch the response body in your catch block using":
#########################################################
catch {
$streamReader = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream())
$ErrResp = $streamReader.ReadToEnd() | ConvertFrom-Json
$streamReader.Close()
}
#########################################################
Thanks again for the quick and successful help
1
Answers
There should still be a message/response of some sort from the API even in the case of a failed request. Perhaps try checking the response information for a 'success' key with a true or false value in the response body and using that as the confirmation of a successful call.
Hi Jamie,
Thank you for your quick reply.
I may not be understanding the answer correctly. I have little to no experience in calling API from Powershell with the Invoke-Restmethod method.
The problem is that when the API call is successful, the response is filled and looks like this:
#####################################
{
"status": {
"success": true,
"info": [
"@{level=info; code=E_OK; message=Success.}"
]
}
}
######################################
If the API call fails, the response is completely empty.
I can of course catch the exception via the catch block, but the exception only contains basic error information.
In the response body, on the other hand, as I saw in postman, the information is very granular and is better used for sensible error messages.
Did I understand correctly what you advised? If not, could you please explain it again for me?
Best regards and many thanks
Rainer
If I'm understanding what you've described, I would think the failure from PowerShell would not have been an API response or maybe the value of $Result needs to be converted to plaintext or JSON. I could be wrong. I'm also not very familiar with requests from PS. You should get back a readable error in JSON as you've noted you do from Postman (except if there were some kind of network failure, timeout, etc. that wouldn't return as JSON). Any clue as to what the errors are when you catch them in PS?
Yes, when I evaluate the exception via the catch block I get the following:
#########################################
Invoke-RestMethod : The remote server returned an error: (400) Invalid request.
In line:44 char:11
+ $Result = Invoke-RestMethod -Uri "https://x.x.x.x:y.y.y.y/api/sonic ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
###########################################
The return value of the API is, as already mentioned, much more granular. In this example, I can see it in Postman as I said, it would say the following:
############################################
{
"status": {
"success": false,
"cli": {
"mode": "config_mode",
"depth": 1,
"command": "address-object ipv4 test1",
"configuring": true,
"pending_config": false,
"restart_required": "FALSE"
},
"info": [
{
"level": "error",
"code": "E_EXISTS",
"message": "Already exists."
}
]
}
}
######################################################
With this information, one know directly that there is already an object with this name. Unfortunately, this cannot be seen from the exception message.