I'm trying using PowerShell to open a web page while sending JSON as my POST data.
Here is what I have
$ie = New-Object -comObject InternetExplorer.Application
$ie.visible = $true
$postBytes = [System.Text.Encoding]::Default.GetBytes('"xCoord":"11.11","yCoord":"22.22","scale":"8,000,016.00","coordSysId":"123"');
$ie.navigate("http://localhost/ProcessSearch", "_blank", $postBytes, "Content-Type: application/json; charset=utf-8")
The web page does open however the JSON isn't getting posted according to Fiddler.
How can I send the POST data?
I would use the cURL utility http://curl.haxx.se/dlwiz/?type=bin&os=Win64 and run it from PowerShell. No need to use IE or any browser for that matter.
I've been looking at something similar and I've posted this http://amonkeysden.tumblr.com/post/5842982257/posting-to-a-restful-api-with-powershell - there's a link to the source there as well but more specifically this is the module:
https://bitbucket.org/thompsonson/powershellmodulerepository/src/5e0afe9d0e26/PsUrl/PsUrl.psm1
and you probably want the New-RestItem function though the Write-URL might do it for you as well.
You should pass the JSON as a string - the example below isn't tested... :).
eg.
New-RestItem http://www.tumblr.com/api/write -Data #{"JSON" = '{"something": "value", "more": {"morekey1":"value", "morekey2": "value"} }'
function New-RestItem {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, Position=0)]
[String]$Url,
[HashTable]$Data,
[TimeSpan]$Timeout = [System.TimeSpan]::FromMinutes(1)
)
Add-Type -AssemblyName System.Web
$formData = [System.Web.HttpUtility]::ParseQueryString("")
foreach($key in $Data.Keys){
$formData.Add($key, $Data[$key])
}
Write-Verbose $formData.ToString()
$reqBody = [System.Text.Encoding]::Default.GetBytes($formData.ToString())
try{
$req = [System.Net.WebRequest]::Create($Url)
$req.Method = "POST"
$req.ContentType = "application/x-www-form-urlencoded"
$req.Timeout = $Timeout.TotalMilliseconds
$reqStream = $req.GetRequestStream()
$reqStream.Write($reqBody, 0, $reqBody.Length)
$reqStream.Close()
$resp = $req.GetResponse()
Write-Verbose $resp
Write-Output $resp.StatusCode
}
catch [System.Net.WebException]{
if ($_.Exception -ne $null -and $_.Exception.Response -ne $null) {
$errorResult = $_.Exception.Response.GetResponseStream()
$errorText = (New-Object System.IO.StreamReader($errorResult)).ReadToEnd()
Write-Warning "The remote server response: $errorText"
Write-Output $_.Exception.Response.StatusCode
} else {
throw $_
}
}
<#
.Synopsis
POSTs the data to the given URL
.Description
POSTs the data to the given URL and returns the status code
.Parameter Url
URL to POST
.Parameter Data
Hashtable of the data to post.
.Parameter Timeout
Optional timeout value, by default timeout is 1 minute.
.Input
URL and a hash of the data to create
.Output
The HTTP Status code (Created (201), Forbidden (403) or Bad Request (400))
.Example
PS:> New-RestItem http://www.tumblr.com/api/write -Data #{"Foo" = "Bar" }
Description
-----------
POST's data to the tumblr write API as application/x-www-form-urlencoded
#>
}
Related
I am badly struck by this problem. I request you to answer or give a hint. I am running out of options.
I am calling an azure runbook upon high CPU utilization via a WebHook. My problem is inside runbook data is not getting decoded properly. For example, the below line is not printing anything.
Write-Output $WebHookData.RequestHeader
Wheras IF i try to explictly convert the data to JSON, like this
*$WebhookData = ConvertFrom-Json $WebhookData*
then it is a throwing error.
ConvertFrom-Json : Invalid JSON primitive: . At line:6 char:31 +
$WebhookData = $WebhookData | ConvertFrom-Json
By the way, I am trying to use the runbook available on Azure gallery {Vertically scale up an Azure Resource Manager VM with Azure Automation}
My Webhook is called from alert created on VM.
A very strange observation:
Working WebHood Example (found in an example) {"WebhookName":"test1","RequestBody":" [\r\n {\r\n \"Message\": \"Test Message\"\r\n }\r\n****]****"
Not Working(the data sent upon calling runbook from VM):
{"WebhookName":"test2","RequestBody":" {\"schemaId\":\"AzureMonitorMetricAlert\"}}
Thanks
I was getting the same error. From my testing, it appears that when performing a "Test" of the runbook, the Webhook data is received as plain text, but when invoked remotely it comes through already formatted as JSON. Here was my solution to cover both scenarios and so far has been working well...
Param (
[object] $WebhookData
)
# Structure Webhook Input Data
If ($WebhookData.WebhookName) {
$WebhookName = $WebhookData.WebhookName
$WebhookHeaders = $WebhookData.RequestHeader
$WebhookBody = $WebhookData.RequestBody
} ElseIf ($WebhookData) {
$WebhookJSON = ConvertFrom-Json -InputObject $WebhookData
$WebhookName = $WebhookJSON.WebhookName
$WebhookHeaders = $WebhookJSON.RequestHeader
$WebhookBody = $WebhookJSON.RequestBody
} Else {
Write-Error -Message 'Runbook was not started from Webhook' -ErrorAction stop
}
I tried with a webhook, the script Write-Output $WebHookData.RequestHeader should work fine.
And if I use ConvertFrom-Json $WebhookData, I can reproduce your issue, not sure why it occurred, according to the doc, the $WebhookData is also in a JSON format, if it is accepted, you could use ConvertFrom-Json -InputObject $WebhookData.RequestBody, it will work fine.
My runbook:
param
(
[Parameter (Mandatory = $false)]
[object] $WebhookData
)
if ($WebhookData) {
Write-Output $WebhookData.RequestHeader
$Body = ConvertFrom-Json -InputObject $WebhookData.RequestBody
Write-Output $Body
} else
{
Write-Output "Missing information";
exit;
}
The powershell script I used to send a webhook:
$uri = "https://s5events.azure-automation.net/webhooks?token=xxxxxxxxxxxx"
$vms = #(
#{ Name="vm01";ResourceGroup="vm01"},
#{ Name="vm02";ResourceGroup="vm02"}
)
$body = ConvertTo-Json -InputObject $vms
$header = #{ message="StartedbyContoso"}
$response = Invoke-WebRequest -Method Post -Uri $uri -Body $body -Headers $header
$jobid = (ConvertFrom-Json ($response.Content)).jobids[0]
Output:
I had the same problem use following to get webhookdata if using test pane with Alert json as input
if(-Not $WebhookData.RequestBody){
$WebhookData = (ConvertFrom-Json -InputObject $WebhookData)
}
$RequestBody = ConvertFrom-JSON -InputObject $WebhookData.RequestBody
This is my first time reaching out on here.
I am trying to create a script for Ivanti Appsense using json code powershell, but i hit an issue
i keep getting a return message "te request is invalid" i am hoping i can get some help
so in powershell this is my code
$url = "http://server/path/api/ImmediateTask"
$cred = Get-Credential
$body = #"
{
"id":"the ID",
"operations" = [
{
"windowsSettingsGroupDisplayName": "_Active Setup",
"operation":{
"liveSettingsDelete":{
"deleteRegistry": true,
"deleteFiles": true,
"preserveArchives": true
}
}
}
"#
$request = Invoke-RestMethod -Method post -Credential $cred -Uri $url -Body $body -ContentType "application/json"
$request
however when i run it and use the correct credentials this is my output
This might not be the whole answer to your problem, but one issue is you're sending invalid json to the API.
You can use PowerShell's features to generate the json string programmatically rather than do it by hand yourself. This way PowerShell will give you more meaningful error messages if your syntax is invalid, rather than waiting for the API to give you a generic "An error has occurred" message:
$data = [ordered] #{
"id" = "the ID"
"operations" = #(
[ordered] #{
"windowsSettingsGroupDisplayName" = "_Active Setup"
"operation" = [ordered] #{
"liveSettingsDelete" = [ordered] #{
"deleteRegistry" = $true
"deleteFiles" = $true
"preserveArchives" = $true
}
}
}
)
};
$json = ConvertTo-Json $data -Depth 99;
write-host $json
#{
# "id": "the ID",
# "operations": [
# {
# "windowsSettingsGroupDisplayName": "_Active Setup",
# "operation": {
# "liveSettingsDelete": {
# "deleteRegistry": true,
# "deleteFiles": true,
# "preserveArchives": true
# }
# }
# }
# ]
#}
$data is basically building a nested hashtable structure, which PowerShell (and your IDE) will warn you about if you have missing brakcets, unclosed quotes, etc.
ConvertTo-Json converts this structured object into a json string.
You might still get errors from your API after doing this, but at least you'll know your json is valid.
I want to send a serialized .json file to a PowerShell Azure Function, prettify it, then return the file to Flow for further processing. I cannot figure out how to do this.
In Flow:
Trigger: Button push
Action1: Get file content from OneDrive
Output:
{
"$content-type": "application/octet-stream",
"$content": "eyJUb3BQYXJlbnQiOns...<truncated for this post>"
}
Action2: Send HTTP Request
URI: https://test.azurewebsites.net/api/prettifyJson?code=<api key>
Method: POST
Body: body('Get_file_content') (output from Action1)
In Azure Function:
Default PowerShell run.ps1:
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with body of the request.
$content = $Request.Query.baz
if (-not $name) {
$name = $Request.Body.baz
}
if ($name) {
$status = [HttpStatusCode]::OK
$body = "Hello $name"
}
else {
$status = [HttpStatusCode]::BadRequest
$body = "Please pass a name on the query string or in the request body."
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = $status
Body = $content
})
Issues:
A call to the function fails with Please pass a name on the query string or in the request body. I can see why, but do not know what syntax to replace in run.ps1
I have no idea what syntax to use to:
a. Receive the .json file
b. Convert it to pretty json
c. Repackage the .json file
d. Send it back to Flow
Looking for guidance.
About number one, seems you're missing the name in the url.
try to replace from this:
https://test.azurewebsites.net/api/prettifyJson?code=
to this:
https://test.azurewebsites.net/api/prettifyJson?name=test&code=
about your second question, the you'll need to parse the body content as Hashtable. try to combine:
$hash = $Request.Body | ConvertFrom-Json -AsHashtable
then all the variables will be available using $hash[]
e.g: $hash["$content"]
Thought this would be pretty simple, but alas, I can't figure it out. It appears that PowerShell will prettify JSON with a single cmdlet.
Goal: Prettify JSON using a PowerShell Azure Function app
Using Microsoft Flow, send an HTTP request (POST) to an Azure Function w/ "ugly", serialized JSON file in body
Azure Function reads file in (then uses ConvertToJson cmdlet to prettify?) and outputs the file back to Flow
Questions:
What do I put in the run.ps1 area of the Azure Function to make this happen?
What do I put in the functions.json area of the Azure Function to make this happen?
I have taken below serialize string
'{ "baz": "quuz", "cow": [ "moo", "cud" ], "foo": "bar" }'
which was mentioned in Prettify json in powershell 3
Here is my function which i used with HttpPost and send the request:
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with query parameters or the body of the request.
$name = $Request.Query.baz
if (-not $name) {
$name = $Request.Body.baz
}
if ($name) {
$status = [HttpStatusCode]::OK
$body = "Hello $name"
}
else {
$status = [HttpStatusCode]::BadRequest
$body = "Please pass a name on the query string or in the request body."
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = $status
Body = $body
})
and below you can see , i am able to read it from the string which i posted.
You can use ConvertFrom-Json to convert it but i wondering if you even need it as you can access it by doing below:
$name = $Request.Query.baz
my binding is same as yours. Hope it helps.
Let me know if you still need any help.
Are you looking for something like this?
using namespace System.Net
param($Request, $TriggerMetadata)
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = $Request.RawBody | ConvertFrom-Json | ConvertTo-Json
})
I am still new to Powershell and haven't been able to find anything on this. I am running a REST GET request to a URI which I know for a fact returns a 404 from the server since the resource is not found.
I would like to be able to run a conditional that checks if it's a 404 and skip over it for further processing if this is the case however when I assign the request to a variable, then calling on that later, it just gives me the contents of what my request was. I have never seen anything like this before in other languages...
My basic premise is the following. I first fetch all group names, then loop through that array of names, include the current one in a new URL and make an additional request for that specific group which looks for a SHIFT which will always have the same name. If the group doesn't have that shift by name I want to skip to the next group, otherwise alter some attributes of that newly found shift object.
Here is what my code looks like, as you can see it's not acting correctly
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$user = '******'
$pass = ConvertTo-SecureString '*******' -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $pass
$req = Invoke-WebRequest -Credential $cred -Uri https://********-np.xmatters.com/api/xm/1/groups
$res = ConvertFrom-Json $req.Content
$content = $res.data
$base = "https://********-np.xmatters.com/api/xm/1/groups"
$group_name = $content[0].targetName
$path = "$base/$group_name/shifts/MAX-Default Shift"
$shift = Invoke-RestMethod -Credential $cred -Uri $path
Write-Host '-----------------------'
Write-Host $shift
Write-Host '-----------------------'
... RESPONSE BELOW ....
Invoke-RestMethod : The remote server returned an error: (404) Not Found.
At \\MMFILE\********$\MyDocuments\Group Supers PReliminary.ps1:16 char:10
+ $shift = Invoke-RestMethod -Credential $cred -Uri $path
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
-----------------------
#{id=***********; group=; name=MAX-Default Shift; description="; start=2018-08-21T04:00:00.000Z; end=2018-08-22T04:00:00.000Z; timezone=America/New_York; recurrence=;
links=}
-----------------------
PS C:\WINDOWS\system32>
What I would like to do is something like, in shorthand code, if $shift.code == 404 ... skip ... else ... run additional query
You need to use a try ... catch.
$code = ""
try{
$shift = Invoke-RestMethod -Credential $cred -Uri $path
}
catch{
$code = $_.Exception.Response.StatusCode.value__
}
if($code -eq "404")
{
continue
# Other things
}
else
{
Write-Host '-----------------------'
Write-Host $shift
Write-Host '-----------------------'
}
You could suppress the error message via Try..Catch and in so doing allow the script to continue:
Try {
$Shift = Invoke-RestMethod http://www.google.com/fakeurl -ErrorAction Stop
#Do other things here if the URL exists..
} Catch {
if ($_.Exception -eq 'The remote server returned an error: (404) Not Found.') {
#Do other things here that you want to happen if the URL does not exist..
}
}
Note this will hide all terminating errors from Invoke-ResetMethod. You could then use an if statement to see if the exception was a 404 and then perform further actions accordingly.