I'm trying to write a program that deletes files from a specific device. The device has a REST API and I can access it from the CLI without any problems.
For example if I write this in the CLI, it works :
$clip="test.mov"
$ClipsURL="http://123.45.67.89/clips"
$ClipToDelete=#{action="delete";clipname=$clip}
Invoke-RestMethod -Uri $ClipsURL -Body $ClipToDelete -Method Post -ContentType "application/x-www-form-urlencoded"
I can play around with the $ClipToDelete parameter (changing the value of $clip) and it works every time.
Now when I put that in a loop (in my main script) it works the first time, and times out next.
foreach($clip in $ListClips) {
$clip="test.mov"
$ClipsURL="http://123.45.67.89/clips"
$ClipToDelete=#{action="delete";clipname=$clip}
Invoke-RestMethod -Uri $ClipsURL -Body $ClipToDelete -Method Post -ContentType "application/x-www-form-urlencoded"
}
While debuging I can clearly see that all the values passed as parameters to Invoke-RestMethod are correct (the URL & Body are correct).
My first impression is that I should probably close the session (if that makes any sense) before trying to Post again.
I tried adding a SessionVariable parameter to the command but it didnt change a thing
Does anyone already know how to close a web sesion left open (with the new Invoke-RestMethod command) ? Or does anyone think that the issue lies elsewhere ?
Thank you.
I had faced similar issues while invoking REST APIs from AirWatch.
Evidently the bug has been filed for POST & DELETE methods below:
https://connect.microsoft.com/PowerShell/feedback/details/836732/tcp-connection-hanging-in-close-wait-when-using-invoke-restmethod-with-put-or-delete
But I did face this issue intermittently with GET requests too, I documented the workarounds I had to use in the below TechNet Wiki article, Maybe you can try those and improve it if you find something extra :
http://social.technet.microsoft.com/wiki/contents/articles/29863.powershell-rest-api-invoke-restmethod-gotcha.aspx
foreach($clip in $ListClips) {
$clip="test.mov"
$ClipsURL="http://123.45.67.89/clips"
$ClipToDelete=#{action="delete";clipname=$clip}
Invoke-RestMethod -Uri $ClipsURL -Body $ClipToDelete -Method Post -ContentType "application/x-www-form-urlencoded"
}
In the second line you are overriding the current value with "text.mov".
If it's not a typo error, it could be that you delete the object the first time and you receive timeouts when trying to delete it again (it depends of course on the server-side implementation)
Related
I am trying to extract a streaming response from a standard http GET call using PowerShell.
I tried to do something like using this Invoke-RestMethod method, such as:
$response = Invoke-RestMethod -Uri $uri -Method GET -Headers $headers -Body
and then tried doing various things like accessing the streaming response in this way:
$Stream.Write($response.Content)
or
$Stream.Write($response.RawContentStream)
but nothing works.
In the end, I found out the following command does both the call and the response along with allowing you to save the result to a file directly. This surprised me because the response is a multipart record that includes headers and other data, not just the chunked file in the stream. But the folks at MS apparently knew that 99% of the time with a chunked reply, the user only wants to save the streamed chunks of data into the file, without the other response header data.
$Response = Invoke-WebRequest #Params -Headers $headers -outfile $TempZipFileName
The key here is using the Invoke-WebRequest call with the -outfile option. This saved me a lot of headache and was super simple to use.
There's been a few similar posts on this but none quite the same (or they don't describe the issue clearly, if they are the same).
I've got a script which makes one API call using Invoke-RestMethod and then iterates over the result of that call making other calls with values from it. The value substitution etc is fine, and I can see (both by dumping the Uri out with Write-Host, and also from the API logs itself) that the calls are being made successfully.
If I do this:
$team = #{ "id" = 5 }
$response = Invoke-RestMethod -Uri https://theUri/$($team.id) -Headers $header -Method Get
then $response is populated as you'd expect and contains the json response from the API endpoint. Response time is a few hundred milliseconds.
If, on the other hand, I have an array of team objects and do this:
foreach ($team in $teams)
{
$response = Invoke-RestMethod -Uri https://theUri/$($team.id) -Headers $header -Method Get
Write-Host $response
}
then it iterates over the whole of the $teams array and outputs empty values on each of the Write-Host lines (the same occurs no matter what you do with it, I'm just using Write-Host as an example here; sending it to Select-Object etc shows it's still blank).
Is this deliberate? I assume no, because it's mad. I've got a temporary workaround by (yes, it's this awful...) writing out the results of the first Api call to a file, then iterating over that list calling a script that does the subsequent calls without the foreach loop in the script for each row. Is there a better way?
I've tried -DisableKeepAlive - no difference. I've tried setting the -TimeoutSec value to a small number, a big number, etc - no difference. I've tried -OutFile and that writes out a bunch of empty files.
It feels - without any evidence for this - that when called inside the loop it's waiting for the HTTP response (which is a 200) and then not downloading any of the response body.
This is Powershell 7.1.3, btw.
Cheers in advance!
I'm trying to make a PowerShell script, which will be run from a power-automate flow, and which in turn is supposed to call different power-automate flows via a Http request, the Url used here is generated by power-automate flow. My issue arise when I try to do
Invoke-Webrequest -Uri https://xxxx-xxx.westeurope.logic.azure.com:xxx/workflows/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/triggers/manual/paths/invoke?api-version=2016-06-01%26sp=%2Ftriggers%2Fmanual%2Frun%26sv=1.0%26sig=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxx -Method POST -Body $PostParams
And when this is run, I get the error of
The Api-Version '2016-06-01&sp=/triggers/manual/run&sv=1.0&sig=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx-rmZzrBfsAvjCc' is not valid. It goes on to suggest some valid ones, which among them are '2016-06-01'.
I have tried removing %26sp, which also did not work. I've tried searching up any information regarding Api-version is not valid, but yielded no result.
I think you should do Invoke-RestMethod
$request = 'https://put_here_your_uri'
$result = Invoke-RestMethod -Method Post -Uri $request
And if you have header like bearer token add -Headers $headers
$headers = #{
'Authorization' = 'bearer HERE_BEARER_TOKEN'
}
Turns out, after quite a bit of back and forth and with an external answer I found out the URL had to be encoded before I could use it in my code
I am trying to upload a file to a URL. I have tried both these approaches:
Invoke-RestMethod -Uri $uploadUrl -Method Put -Headers $uploadHdrs -InFile $uploadFilePath
Invoke-RestMethod -Uri $uploadUrl -Method Put -body $uploadFileBody -Headers $uploadHdrs
Error I am getting:
Invoke-RestMethod : You must write ContentLength bytes to the request stream
before calling [Begin]GetResponse.
If I add in the -TransferEncoding param, I get errors from the server saying unsupported.
What can I do to include the content length?
I think you'll need to use a different command, like Invoke-WebRequest or even better call the .NET WebClient.UploadFile() or .UploadData methods directly from PowerShell.
While REST methods might conceptually include uploading files, that doesn't mean that the Invoke-WebRequest command has been tested as supporting your scenario. I'd suggest going lower-level (like WebClient) because we know more scenarios have been tested (by the larger .NET team), and there are a wide variety of methods on WebClient for supporting specific scenarios.
One example you might find helpfull in how to invoke these methods from PowerShell is at https://social.technet.microsoft.com/Forums/windowsserver/en-US/0c268c7e-674c-49bc-9933-a87a95f8f44c/powershell-webclientuploadfile?forum=winserverpowershell
P.S. The message your are getting about the request stream is coming from an even lower level .NET API, but WebClient is simpler to use, should take care of setting ContentLength properly and hopefully is "just right" for your need.
I am using a PowerShell module to interact with a manufacturer's REST API. The module is written by the manufacturer and makes use of the Invoke-RestMethod built in function.
I noticed when running my program with few outputs turned on that I was getting a ton of lines appearing in the console. I had never seen that before, so i decided to dig in. I traced the issue down to a single line of code:
Invoke-RestMethod -Headers $session.DirectoryAuthHeader -Uri $uri -Method $Method -Body $Body
I further instrumented it bu outputting to the console all of the variables that are being sent to the function. This issue only seems to happen when Invoke-RestMethod is using the PUT method. GET and POST do not yield any new lines. I took a look at the transactions in Fiddler and the only thing that jumped out at me was the PUT method returned a blank body.
Any ideas? I'm hoping this is just an issue with the way Invoke-RestMethod is being called and not the method itself. Thanks.
I ended up solving the issue myself. I'm still not 100% why PowerShell is functioning this way, but basically the blank return value (because there is no body in the response) is getting echoed to the command line. I fixed the issue by checking if the body was empty, and if not returning null instead of an empty PSObject which I believe is what was happening.
$RESTResponse = Invoke-RestMethod -Headers $session.DirectoryAuthHeader -Uri $uri -Method $Method -Body $Body
if ($RESTResponse -ne "") {
return $RESTResponse
} else {
return
}
As I've done some more learning in PowerShell I found out what this is happening and wanted to share it for anyone else who comes across this problem.
In PowerShell there is a concept called the pipeline. Basically what happens is if cmdlets are called in succession using the pipeline character "|", the output from the preceding function becomes the input of the next function and so on. If there is output on the pipeline that isn't handled (e.g. putting it in a variable) it will eventually be echoed to the host.