Powershell Invoke-WebRequest casting issue on PS3 not PS4 - powershell

I run the following command in my PS script:
$apiResult = Invoke-WebRequest -Uri $myURL -Body $body -DisableKeepAlive -Headers $headers -Method Post -TimeoutSec 120 -ContentType $contentType -UseBasicParsing
This fails on the following error:
Unable to cast object of type \u0027System.Management.Automation.PSObject\u0027 to type \u0027System.String\u0027
Here is the catch:
The types of the supplied variables are System.String (for $body, $myURL, $contentType) and System.Collection.Hashtable (for $headers)
This fails without calling the actual service behind the URL (verified in service logs)
Running this script with the same parameters on the machine with Powershell version 4 does not create this error and actually returns expected result
I believe this is a bug but i have not been able to find any mention of it on google or any other areas including documentation.

Well...After long time digging I found that the issue was one of the values in my headers hashtable was not a string! not sure why this passes on powershell 4...maybe the casting there is more flexable than in PS3

Related

Cant' Access API with Powershell but can access using Postman, Python, or cURL

I'm trying to get data back from an API online using Powershell with the command Invoke-WebRequest -UseBasicParsing $request_string -Method Get -Headers $headers) but am getting back Invoke-WebRequest : The remote server returned an error: (403) Forbidden.
I am supplying a $headers dictionary. Strangely, I can access the API using Postman, Python, and cURL. It's only when using Powershell commands that I get the 403 error. In fact, I used Postman's Code Snippet feature to generate my Powershell code, and it still doensn't work! Postman's Powershell Code Snippet was:
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer {removed for security}")
$response = Invoke-RestMethod '{removed for security}' -Method 'GET' -Headers $headers
$response | ConvertTo-Json
To recap, both Invoke-WebRequest and Invoke-RestMethod don't work.
Any help here is much appreciated.
Thanks!
Figured it out on my own.
The API vendor enforced https requirement instead of just http. Apparently, Postman, Python, and cURL can figure that out on their own and change the request accordingly, but Powershell cannot.

Powershell equivalent to curl -F to upload a file

I need to upload files via commandline / powershell.
It works fine with
curl -F "file=#test.txt" https://api.anonfiles.com/upload
However, curl does not exist on Windows Server 2016 and I do not want to tell my clients to set it up. So I am looking for a powershell alternative to accomplish this task. I tried various solutions, but none of them worked. What I tried so far:
(1)
$postParams = #{file='C:\users\user\testfile.txt'}; Invoke-WebRequest -Uri https://api.anonfiles.com/upload -Method POST -Body $postParams
(2)
Invoke-WebRequest -UseBasicParsing https://api.anonfiles.com/upload -ContentType "application/json" -Method POST -InFile "C:\users\user\testfile.txt"
(3)
$file=[io.file]::readallbytes('c:\users\user\testfile.txt')
Invoke-WebRequest -UseBasicParsing https://api.anonfiles.com/upload -ContentType "application/json" -Method POST -Body "{ '#file':'"$file"'}"
None of it works. I canot believe it's so hard to replace an curl oneliner in powershell... The error in each case is a 400 http error, the request is wrong.
How do I send the above mentioned curl-request equivalent in powershell? The site is https://anonfiles.com/docs/api
I gave up. It's not possible in Powershell.
My App will just download curl.exe as standalone from now on, if it's not there.

Weird behavior while invoking Rest call using Invoke-RestMethod on Powershell script

I want to pass body(parameters) to Rest-call using Invoke-RestMethod(powershell script) in GET call. but I think it's not supported because of some security reasons(some RFC standards).
But in single session, When I first use POST method and then if I use GET method then it works. but if I directly call get method then it's throwing below error.
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send
So, Is there some information powershell stores after first call ? Also, Is there any way to pass parameters to "GET" Restcall in powershell script ?
I've attached code snippet:
this snippet is working.
Invoke-RestMethod 'https://test_url/url_path?param1=par' -Method 'POST' -Headers $headers
Invoke-RestMethod 'https://test_url/url_path?param1=par' -Method 'GET' -Headers $headers # works
but this throws the error,
Invoke-RestMethod 'https://test_url/url_path?param1=par' -Method 'GET' -Headers $headers #Not works

How to download a file accepting license using powershell

I am trying to download package from the below link using powershell.
https://www.tenable.com/downloads/nessus-agents
i do not have direct link for these package also when i click on download it ask to agree. I was able to do it on Linux using command shown below. Kindly advise how can i do it in windows.
"wget --no-check-certificate --post-data='accept="I accept the terms of this license"&x=""&sid=5mcia8gchg28attkc9oarah153&p=NessusAgent-7.4.2-amzn.x86_64.rpm' 'https://www.tenable.com/downloads/nessus-agents' -O NessusAgent-7.4.2-amzn.x86_64.rpm"
could not find anything tried option with invoke-webrequest
Invoke-RestMethod -Uri 'https://www.tenable.com/downloads/nessus-agents'
There's a GET query string parameter that indicates acceptance.
Simply add i_agree_to_tenable_license_agreement=true to your query string parameters.
Invoke-WebRequest -Uri 'https://www.tenable.com/downloads/api/v1/public/pages/nessus-agents/downloads/9762/download?i_agree_to_tenable_license_agreement=true' -OutFile 'NessusAgent-7.4.2-x64.msi'
You can easily get the IDs of the other files from their API endpoint like so:
(Invoke-WebRequest -Uri 'https://www.tenable.com/downloads/api/v1/public/pages/nessus-agents' | ConvertFrom-Json).downloads | Format-Table -AutoSize
This is similar syntax in Powershell, but it's just downloading a file with contents "OK".
$body = 'accept="I accept the terms of this license"&x=""&sid=5mcia8gchg28attkc9oarah153&p=NessusAgent-7.4.2-amzn.x86_64.rpm'
$uri = 'https://www.tenable.com/downloads/nessus-agents'
$resp = Invoke-WebRequest -Method Post -Body $body -Uri $uri -OutFile .\NessusAgent-7.4.2-amzn.x86_64.rpm
Maybe the "sid" variable needs to change per request.

Unsupported Media Type when updating values using the TeamCity REST API

I have a Powershell script that I use to synchonize various projects parameters. The relevant code I use to update a project parameter is:
$propName = "ReleaseNumber"
$propValue = "10.0"
Invoke-RestMethod -method Put -uri "$server/httpAuth/app/rest/projects/$targetProject/parameters/$propName" -Body "$propValue"
After the upgrade to TeamCity 9.1, I started receiving the following error when using the script:
Invoke-RestMethod : The remote server returned an error: (415) Unsupported Media Type.
What do I need to do to resolve this issue?
By default, the ContentType sent by Powershell's Invoke-RestMethod is application/x-www-form-urlencoded. Prior to TeamCity 9.1, TeamCity didn't seem to care much about the ContentType for the project-related API calls, but with 9.1, and the addition of both XML and JSON payloads, it looks like TeamCity is being more picky about content types. So, since your property values are just plain text, to resolve the problem specify text/plain as the ContentType, like so:
Invoke-RestMethod -contentType "text/plain" -method Put -uri "$server/httpAuth/app/rest/projects/$targetProject/parameters/$propName" -body "$propValue"