PowerShell Invoke-WebRequest | API Call - json

I'm using Gitea and I try to create a user using an API call in PowerShell:
Testing Plateforme : https://try.gitea.io/
API URL : https://try.gitea.io/api/swagger
API Token : 3bb81a498393f4af3d278164b5755fc23b74b785
Username : Will-stackoverflow
Password : willwill
Here it's what I have tried so far :
# Filling my var with some data
$username="myuser"
$email="myuser#mydomain.com"
$full_name="My User"
$password="P#$$w0rd"
# Building a hash with my data
$hash = #{
Email = $($email);
full_name = $($full_name);
login_name = $($username);
Password = $($password);
send_notify = "false";
source_id = 0;
Username = $($username)
}
# Converting my hash to json format
$JSON = $hash | convertto-json
# Displaying my JSON var
$JSON
Invoke-WebRequest -uri "http://try.gitea.io/api/v1/admin/users?access_token=3bb81a498393f4af3d278164b5755fc23b74b785" -Method POST -Body $JSON
My $JSON var is fed properly :
{
"Password": "P#w0rd",
"full_name": "My User",
"Username": "myuser",
"Email": "myuser#mydomain.com",
"source_id": 0,
"login_name": "myuser",
"send_notify": "false"
}
But there is the result (from my prod environement as I can't get it to work at all using the online plateforme) :
To me it sounds like the fields "Username", "Email" and "Password" are required, but they are filled in my displayed JSON. What am I missing or doing wrong ?
EDIT :
Adding the -ContentType 'application/json' parameter to the Invoke-WebRequest command as suggested by Theo :

Looking at the Swagger UI site, it seems to me the json must contain properties in lower-caps only
{
"email": "myuser#mydomain.com",
"full_name": "My User",
"login_name": "myuser",
"password": "P#w0rd",
"send_notify": $true,
"source_id": 0,
"username": "myuser"
}
Also, according to the Swagger site, you need to state the -ContentType.
Your code would look like this:
# Filling my var with some data
$username="myuser"
$email="myuser#mydomain.com"
$full_name="My User"
$password="P#$$w0rd"
# Building a hash with my data
$hash = #{
email = $($email); # string
full_name = $($full_name); # string
login_name = $($username); # string
password = $($password); # string
send_notify = $false; # boolean
source_id = 0; # int
username = $($username) # string
}
# Converting my hash to json format
$JSON = $hash | ConvertTo-Json
# Displaying my JSON var
$JSON
# just to make it somewhat easier on the eyes
$token = "3bb81a498393f4af3d278164b5755fc23b74b785"
$url = "http://try.gitea.io/api/v1/admin/users?access_token=$token"
Invoke-WebRequest -uri $url -Method POST -Body $JSON -ContentType 'application/json'

Related

Invoke-ResMethod Rest API

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.

Invoke RestMethod issues parsing JSON: Value not convertible to Int

I have to use PowerShell to manage a Websense server via API. I am using Invoke-RestMethod and I am using a json format to make the changes. The comand to the server is as follows:
Invoke-RestMethod -Uri $uriCreate -Method Post -Headers $headers -Body ($jsonCat | ConvertTo-Json) -ContentType "application/json"
My variables are as follows:
$uriCreate = https://<ipaddress>:<port>/api/web/v1/categories
$headers = #{ Authorization = <credentials> }
$jsonCat = [ordered]#{
"Transaction ID" = $transID
Categories = #(
[ordered]#{
"Category Name" = $catName
"Category Description" = $catDesc
"Parent" = $catID
}
)
}
When I attempt to create the category via Powershell I get the following error returned:
Invoke-RestMethod : {
"Error" : [ "Could not parse JSON: Value is not convertible to Int." ]
}
Any idea what I am doing wrong?

Powershell Invoke-Webrequest w/ JSON Body - Can not deserialize...?

I need to perform an Invoke-Webrequest with a specifically formatted body to add devices to a product. Here is what it looks like in json (example straight from the vendor's documentation):
$body_json = '{"datasource": [{
"parentId": "123456789000",
"name": "(name)",
"id": "(value)",
"typeId": 0,
"childEnabled": false,
"childCount": 0,
"childType": 0,
"ipAddress": "(ipAddress)",
"zoneId": 0,
"url": "(url)",
"enabled": false,
"idmId": 123456789000,
"parameters": [{
"key": "(key)",
"value": "(value)"
}]
}]}'
When I try to submit this in its json representation though, I get the following error:
Invoke-WebRequest : Can not deserialize instance of
com.vendor.etc.DataSourceDetail out of START_ARRAY token at [Source:
java.io.StringReader#22c614; line: 1, column: 1] At
C:\powershell_script_location\ps.ps1:114 char 9
+ $request = Invoke-WebRequest $url -Method Post -Headers $headers -Body $body_json - ...
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation:
(System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest],
WebException + FullyQualifiedErrorId :
WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
The issue is with the format of the "parameters", parameter because the request submits fine when omitting the "parameters", but then the
devices that I'm adding are missing important parameter details.
Is there something wrong with Invoke-WebRequest, JavaScriptSerializer,
the vendor's code, or is this a user error? Let me know if any clarification is needed.
Unfortunately I don't know what a com.vendor.etc.DataSourceDetail instance looks like, as I am using an API and I don't have access to it directly.
Use Invoke-RestMethod instead of Invoke-WebRequest.
If you have the body as a string use:
Invoke-RestMethod -Uri http://your-url.com -Method POST -Body $body_json -ContentType "application/json"
If the body must be constructed from data/parameters, it might be easier to build a hashtable and convert it to json via ConvertTo-Json:
$body_json = #{
datasource = #(
#{
parentId = 123456789000
name = "name"
id = "value"
typeId = 0
childEnabled = $false
childCount = 0
childType = 0
ipAddress = "ipAddress"
zoneId = 0
url = "url"
enabled = $false
idmId = 123456789000
parameters = #( #{
key = "key"
value = "value"
})
})} | ConvertTo-Json -Depth 4
Invoke-RestMethod -Method 'Post' -Uri http://your-url.com -Body $body_json -ContentType "application/json"
Body Undefined
I couldn't understand why the req.body on the server was undefined (NodeJS Azure Function). It turns out I had a header that was an empty string.
It's not clear whether is was invoke-restmethod or azure-functions-core-tools that has a bug.
FWIW.

Powershell ConvertTo-JSON returning "nested" object

I'm trying to make a POST request to my server. Everything was fine until I decided to convert my object to JSON. Here's my code:
$postParams = #{
Login = "JonSnow66";
Password = "LetItSnow";
Email = "Jon.Snow#wall.com";
Name = "Jon Snow";
Desc = "I know nothing";
BirthDate = "1572 2 16";
Img = Get-Content -Path ./PH_img.txt | Out-String;
Type = "Admin";
}
Invoke-WebRequest -Uri http://localhost:3000/api/add/user -Method POST -Body (ConvertTo-Json $postParams -Compress)
Instead of returning regular JSON object like:
{
"Login": "JonSnow66"
...
}
It returns:
{{
"Login": "JonSnow66",
"BirthDate": "1572 2 16",
"Desc": "I know nothing",
"Name": "Jon Snow",
"Type": "Admin",
"Password": "LetItSnow",
"Img": "/9j/4<BASE64>/Z\r\n",
"Email": "Jon.Snow#wall.com"
}: ""}
I'm just a powershell beginner.
I think you need to specify ContentType on Invoke-WebRequest to be 'application/json'. If you don't specify a content type and are performing a Post then I think the cmdlet assumes you are submitting a form by default, and that might explain the extra { } characters you are seeing in the result.
Here's the modified code:
Invoke-WebRequest -Uri 'http://localhost:3000/api/add/user' -Method POST -ContentType 'application/json' -Body (ConvertTo-Json $postParams -Compress)

Error Malformed UTF-8 characters, possibly incorrectly encoded

I have a PowerShell script that reads from an Excel file. It stores data from particular cells/columns, converts to JSON and then sends it via REST to my Wordpress install.
The issue I'm having is that when attempting to run the script using data taken from Excel, it presents the error
Malformed UTF-8 characters, possibly incorrectly encoded
#Declare the file path and sheet name
$file = "P:\file.xlsx"
$sheetName = "IN PRODUCTION"
###############################################
# #
# EXCEL FUNCTIONS #
# #
###############################################
#Create an instance of Excel.Application and Open Excel file
$objExcel = New-Object -ComObject Excel.Application
$workbook = $objExcel.Workbooks.Open($file)
$sheet = $workbook.Worksheets.Item($sheetName)
$objExcel.Visible = $false
#Count max row
$rowMax = ($sheet.UsedRange.Rows).count
#Declare the starting positions
$rowName,$colName = 1,1
$rowSignOff,$colSignOff = 1,2
$rowReceived,$colReceived = 1,3
$rowBuildStart,$colBuildStart = 1,4
$rowBuildEnd,$colBuildEnd = 1,5
$rowShipping,$colShipping = 1,6
$rowBuiltBy,$colBuiltBy = 1,7
$rowQA,$colQA = 1,8
$rowCage,$colCage = 1,9
$rowComment,$colComment = 1,10
$rowStatus,$colStatus = 1,11
$build = #()
#Loop to get values and store it
for ($i=1; $i -le $rowMax-1; $i++)
{
$name = $sheet.Cells.Item($rowName+$i, $colName).Text
$signoff = $sheet.Cells.Item($rowSignOff+$i, $colSignOff).Text
$received = $sheet.Cells.Item($rowReceived+$i, $colReceived).Text
$buildstart = $sheet.Cells.Item($rowBuildStart+$i, $colBuildStart).Text
$buildend = $sheet.Cells.Item($rowBuildEnd+$i, $colBuildEnd).Text
$shipping = $sheet.Cells.Item($rowShipping+$i, $colShipping).Text
$builtby = $sheet.Cells.Item($rowBuiltBy+$i, $colBuiltBy).Text
$qa = $sheet.Cells.Item($rowQA+$i, $colQA).Text
$cage = $sheet.Cells.Item($rowCage+$i, $colCage).Text
$comment = $sheet.Cells.Item($rowComment+$i, $colComment).Text
$status = $sheet.Cells.Item($rowStatus+$i, $colStatus).Text
$build += [PSCustomObject]#{
name = $name
start = $buildstart
end = $buildend
by = $builtby
notes = $comment
}
}
###############################################
# #
# POST FUNCTIONS #
# #
###############################################
$content = [PSCustomObject]#{
staging_fields = #{
staging_repeater=$build
}
}
$json = $content | ConvertTo-Json -Depth $([int32]::MaxValue)
Invoke-RestMethod -Uri $uri -Method POST -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -ContentType "application/json" -Body $json
Write-Host $json
#Close excel file
$objExcel.Quit()
The output of Write-Host $json is as below
{
"staging_fields": {
"staging_repeater": [
{
"name": "Test 1",
"start": "19/12/2016",
"end": "09/01/2017",
"by": "JM",
"notes": ""
},
{
"name": "Test 2",
"start": "01/01/2017",
"end": "11/01/2017",
"by": "JC",
"notes": ""
},
{
"name": "Test 3",
"start": "17/01/2017",
"end": "01/02/2017",
"by": "JM",
"notes": ""
}
]
}
}
Pasting this into Postman and sending a POST request produces no errors and successfully adds to my WordPress site.
If it helps, the full error is below
Invoke-RestMethod : {"code":"rest_invalid_json","message":"Invalid JSON body passed.","data":{"status":400,"json_error_code":5,"json_error_message":"Malformed UTF-8
characters, possibly incorrectly encoded"}}
At L:\\Untitled1.ps1:98 char:1
+ Invoke-RestMethod -Uri $uri -Method POST -Headers #{Authorization=("B ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
If I were to replace the variables with strings such as "Test", the script works correctly. Below is an example.
#Loop to get values and store it
for ($i=1; $i -le $rowMax-1; $i++)
{
$name = $sheet.Cells.Item($rowName+$i, $colName).Text
$signoff = $sheet.Cells.Item($rowSignOff+$i, $colSignOff).Text
$received = $sheet.Cells.Item($rowReceived+$i, $colReceived).Text
$buildstart = $sheet.Cells.Item($rowBuildStart+$i, $colBuildStart).Text
$buildend = $sheet.Cells.Item($rowBuildEnd+$i, $colBuildEnd).Text
$shipping = $sheet.Cells.Item($rowShipping+$i, $colShipping).Text
$builtby = $sheet.Cells.Item($rowBuiltBy+$i, $colBuiltBy).Text
$qa = $sheet.Cells.Item($rowQA+$i, $colQA).Text
$cage = $sheet.Cells.Item($rowCage+$i, $colCage).Text
$comment = $sheet.Cells.Item($rowComment+$i, $colComment).Text
$status = $sheet.Cells.Item($rowStatus+$i, $colStatus).Text
$build += [PSCustomObject]#{
name = "test"
start = "test"
end = "test"
by = "test"
notes = "test"
}
}
It appears the data coming from Excel is not coming through with the correct character encoding. This is where I'm at a loss.
I'm an idiot.
Within the excel file, autocorrect had changed cafe to Café which was the cause of the issue. Simply renaming resolved this for me.