I am creating a script to call a couple of endpoints in my service.
The calls look like this:
$scheduleResponse=(curl -Method 'POST' -Uri $baseUrl'/scheduletests' `
-Headers #{"Accept"="application/json";"Content-Type"="application/json"} `
-Body $body)
$scheduleContent=ConvertFrom-Json([String]::new($scheduleResponse.Content))
#Error checks here
$testId = [String]::new($scheduleContent.ScheduleTests.TestID)
$getTestResultsBody = '{"TestID":"' + $testId + '"}' #Hard-coding this value works.
$getResponse=(curl -Method 'POST' -Uri $baseUrl'/gettestresults' -Headers #{"Accept"="application/json";"Content-Type"="application/json"} -Body $getTestResultsBody)
My getResponse fails with this error message:
curl : Unable to read data from the transport connection: The
connection was closed. At C:\Development\Services\TESTService\Test
Clients\Caller.ps1:43 char:27 ... etResponse=(curl -Method 'POST'
-Uri $baseUrl'/gettestresults' -Heade ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : NotSpecified: (:) [Invoke-WebRequest], IOException
FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
I debugged my service and it is receiving the correct request and sending the correct response back.
If I hard-code testId in the getRequest, the whole script works. So my guess is that it has something to do with reading the test id from the first call.
Any pointers on what could be wrong?
Related
I am trying to access the API of OpenProvider using PowerShell and I can't seem to get past Authentication.
The documentation for the API is here : https://support.openprovider.eu/hc/en-us/articles/360025683173-Getting-started-with-Openprovider-API
And my code looks like this:
$EndPoint = "https://api.openprovider.eu/v1beta/auth/login"
function Get-ConfHeaders
{
##Configure headers
$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Headers.Add("ip","0.0.0.0")
$Headers.Add("username","myusername")
$Headers.Add("hash","APIpasswordhashgoeshere")
return $Headers
}
$header = Get-ConfHeaders
Invoke-RestMethod -Method Post -Uri $EndPoint -Headers $header
The response get is :
Invoke-RestMethod : The remote server returned an error: (500) Internal Server Error.
At line:36 char:1
+ Invoke-RestMethod -Method Post -Uri $EndPoint -Headers $header
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I am by no means an expert when it comes to API and any help would be appreciated.
Ok, I think the API documentation here leaves a lot to be desired.
You need to include the authentication in the body and it needs to be converted to JSON format. So the working code looks like this:-
$EndPoint = "https://api.openprovider.eu/v1beta/auth/login"
function Get-ConfHeaders
{
##Configure headers
$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Headers.Add("ip","0.0.0.0")
$Headers.Add("username","username")
$Headers.Add("password","passwordhere")
return $Headers
}
$header = Get-ConfHeaders | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri $EndPoint -body $header -ContentType 'application/json'
Thanks for the help everyone.
I have a POST method that works fine in Postman but I can't get it working in powershell.
The client id and client secret are setup in AWS cognito.
I am using basic authentication to retrieve the access token.
Below is my code,
$encodedlogin="MNBvbmZfYWsxUTRocG1qOG5zOGZqZ8xvN646a1plMDNsMTZjY6xucTA5MzVkOGg2aGdlaG1mdXAxaHZkMmlxaXY0PKOdM3BcxNBtPLs5"
$authorisation = "Basic " + $encodedlogin
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization",$authorisation)
$headers.Add("Accept","application/json")
$headers.Add("Content-Type","application/json")
$headers.Add("ResponseType","id_token")
$body = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$body.Add("grant_type","client_credentials")
$body.Add("scope","cybergate-gateway-resources/cybertron.fullaccess")
$uri = "https://cybergate.auth.eu-west-2.amazoncognito.com/oauth2/token"
$response = Invoke-WebRequest -Uri $uri -Headers $headers -body $body -Method Post -ContentType "application/json"
The error as follows,
Invoke-WebRequest : The remote server returned an error: (405) Method Not Allowed.
At C:\CyberGate\src\CyberGate.API\Scripts\Deploy\CyberGate.ps1:33 char:17
+ ... $response = Invoke-WebRequest -Uri $uri -Headers $headers -body $body ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Any ideas?
Thanks
So, here is the link to Jobs API call in Databricks here
Everything works in Python using requests. E.g both the job creation and job listing works
import requests
proxy= "http://127.0.0.1:8888"
access_token="tokenabc"
proxies = {
"https": proxy,
}
header_read = {
'Authorization': "Bearer " + access_token,
'Accept': "application/scim+json"
}
#list jobs
init_get=requests.get('https://databricksworkspaceid.azuredatabricks.net/api/2.0/jobs/list', headers=header_read, proxies=proxies)
#create job
init_post=requests.post('https://databricksworkspaceid.azuredatabricks.net/api/2.0/jobs/create', headers=header_read, proxies=proxies,verify=False,json=job_payload)
However, strangely in Powershell, only the job creation works and Job listing fails.
#this works
Invoke-RestMethod -Uri 'https://databricksworkspaceid.azuredatabricks.net/api/2.0/jobs/create' -Headers #{ 'Authorization' = "Bearer $bearertoken" } -Method Post -Body $content -ContentType 'application/json'
#this does not work
Invoke-WebRequest -Uri 'https://databricksworkspaceid.azuredatabricks.net/api/2.0/jobs/list' -Headers #{ 'Authorization' = "Bearer $bearertoken" } -Method Get
#RestMethod also does not work
Invoke-RestMethod -Uri 'https://databricksworkspaceid.azuredatabricks.net/api/2.0/jobs/list' -Headers #{ 'Authorization' = "Bearer $bearertoken" } -Method Get
I have also tried setting the Content type on these but nothing helps.
Also, explicitly setting the proxy (fiddler) does not help.
-proxy "http://127.0.0.1:8888"
But should not be the proxy also , as the post method works.
I just keep getting an error like
Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.
At line:22 char:5
+ Invoke-WebRequest -Uri 'https://databricksworkspaceid.azuredatabricks.net/ap ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
or in case of RestMethod
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
At line:22 char:5
+ Invoke-RestMethod -Uri 'https://databricksworkspaceid.azuredatabricks.net/ap ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I could have understood if everything failed in Powershell, but the post method (job creation) works, so not sure, why the connection would be terminated in case of a Get request but not a post.
Going by some forum posts, I have also tried the following but to no avail-
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Does anyone know what am I doing wrong/missing? Baffling to see working in python but only a part in Powershell.
So, I finally found the answer. Basically 2 things:
Had to do this before hitting the list endpoint (strangely as I said- the create endpoint) worked
Basically allowing TLS, TLS1.1 and TLS1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
Doing only point 1 didn't work. I HAD to also use an "elevated" powershell session. Basically running the script with step 1 included, using a "Run as Administrator".
I'm working with an API via PowerShell that returns human-readable errors as a json object in the response body when an error occurs. However, when I attempt to find that json body in an exception, I can see the error, the underlying System.Net.WebException and the further underlying System.Net.HttpWebResponse, but nowhere can I find the actual body they're referring to. Is this something that is accessible?
For example, here is a valid API call that would work:
Invoke-RestMethod -Method Get -Headers #{Authorization="Token token=$YourTokenHere";"Content-type"="application/json"} -Uri "https://mydomain.pagerduty.com/api/v1/users/ABCDEF" -Body #{offset=0;limit=100}
If you then change the user ID at the end of the URI, it fails and you get this error:
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At line:1 char:1
+ Invoke-RestMethod -Method Get -Headers #{Authorization="Token token=b ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I can dive down in to the error to see the underlying error and the response if I do the following and convert to json for easy viewing of subproperties:
$Error[0].Exception.Response | ConvertTo-Json
But no matter how I comb through these errors, I can't seem to find the json body. Where might it be, or how can I capture it? I seem to have the same result if I do a try/catch.
You could read the responsestream so you can get the body of the response. Ex:
try {
Invoke-RestMethod -Method Get -Headers #{Authorization="Token token=$YourTokenHere";"Content-type"="application/json"} -Uri "https://mydomain.pagerduty.com/api/v1/users/ABCDEF" -Body #{offset=0;limit=100}
} catch {
$stream = New-Object System.IO.StreamReader $_.Exception.Response.GetResponseStream()
$json = $stream.ReadToEnd()
$stream.Dispose()
$json
}
Output:
{"error":{"message":"Account Not Found","code":2007}}
I'm trying to work out how to do OData updates using PowerShell as the client. I found the site services.odata.org to use for testing: http://services.odata.org/OData/OData.svc/$metadata.
I've tried this:
Invoke-RestMethod -Method Put -ContentType 'application/json' `
-Uri 'http://services.odata.org/V3/(S(k22mmq0ajlv45epd2psyysnd))/OData/OData.svc/Products(0)' `
-Body ( #{ Description = 'CheesyPeas' } | ConvertTo-Json )
but I get back
Invoke-RestMethod : <?xml version="1.0" encoding="utf-8"?>
<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<m:code />
<m:message xml:lang="en-US">
Error processing request stream. Type information must be specified for types that take part in inheritance.
</m:message>
</m:error>
At line:1 char:1
+ Invoke-RestMethod -Uri 'http://services.odata.org/V3/(S(k22mmq0ajlv45epd2psyysnd ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I think this has something to do with the Navigation Properties. Ideally, I'd be testing against a simple entity with no Navigation Properties until I've got a basic PUT working but I can't find one. Can anyone help me get this working?
As the error said, you need to specify the type you send in the body.
Write your code like below:
Invoke-RestMethod -Method Put -ContentType 'application/json' `
-Uri 'http://services.odata.org/V3/(S(k22mmq0ajlv45epd2psyysnd))/OData/OData.svc/Products(0)' `
-Body ( #{ "odata.type" = 'ODataDemo.Product'; Description = 'CheesyPeas' } | ConvertTo-Json )