OneLogin REST API 与 PowerShell 的 Invoke-RestMethod
OneLogin REST API with PowerShell's Invoke-RestMethod
我正在使用 OneLogin REST API,似乎无法通过 PUT 方法进行任何调用。当我在 Postman 中测试时,我可以像这样传递一个原始的 JSON 正文:
{
"role_id_array": [
115028
]
}
到终点:
https://api.us.onelogin.com/api/1/users//add_roles
这很好用。但是,当我尝试对 PowerShell 的 Invoke-RestMethod 命令执行相同操作时,我收到 400 Bad Request 错误。我的代码如下所示:
$Splat = @{
Method = $Method
Uri = https://api.us.onelogin.com/api/1/users/12345678/add_roles
ContentType = "application/json"
Headers = @{authorization = "bearer:$($Token.access_token)"}
Body = @{role_id_array = @(123456)}
}
Invoke-RestMethod @Splat
到目前为止,我对任何 GET 调用都没有问题,只有 PUT 有问题。此外,如果我 运行 通过 ConvertTo-Json 传递的 Body 哈希表,输出看起来就像上面的工作示例。有没有人知道为什么这不起作用?
好的,所以我崩溃并安装了 Fiddler,我想我正在做点什么。 PowerShell cmdlet 似乎不知道如何处理 application/json 内容类型的数组。我不确定 XML 是否会出现这种情况,因为我还没有测试过。
我将主体更改为使用直 json 弦并且它有效:
$Body = "{ `"role_id_array`": [123456] }"
如果我使用哈希表并将值设置为这样的数组:
$Body = @{role_id_array = 115028,128732}
然后我会收到 400 失败响应。 Fiddler 向我展示了发生了什么——这是原始请求:
PUT https://api.us.onelogin.com/api/1/users/12345678/add_roles HTTP/1.1
授权:bearer:3c93ae2-编辑-
用户代理:Mozilla/5.0(Windows NT;Windows NT 6.3;en-US)WindowsPowerShell/5.1.14394.1000
内容类型:application/json
主持人:api.us.onelogin.com
内容长度:33
role_id_array=System.Object%5b%5d
请注意,数组未正确转换,Invoke-RestMethod 只是将其折叠成类型名称定义,类似于 Export-Csv 处理数组 属性 值的方式。
所以我认为我在使用 PUT 方法时遇到了问题,因为我的所有 GET 调用都在工作,但这是一个转移注意力的问题。真正的问题是处理一个 REST 端点,它需要数组值作为它的请求参数值。
编辑:我发现有人在 2014 年发布了这个问题,但他的解决方案是将 -ContentType 参数设置为 'application/json':
Powershell v4 Invoke-RestMethod body sends System.Object
我已经这样做了,但仍然遇到同样的问题。这是一个错误吗?
我能够 PUT
工作!
如何从 Invoke-RestMethod 获取丰富的错误响应数据
首先,我使用了 this blog post here,它有一个很好的方法来检索 Invoke-RestMethod
或 WebRequest
cmdlet 的完整错误消息。
在他的方法中,首先定义一个名为Failure的Function。
function Failure {
$global:helpme = $body
$global:helpmoref = $moref
$global:result = $_.Exception.Response.GetResponseStream()
$global:reader = New-Object System.IO.StreamReader($global:result)
$global:responseBody = $global:reader.ReadToEnd();
Write-Host -BackgroundColor:Black -ForegroundColor:Red "Status: A system exception was caught."
Write-Host -BackgroundColor:Black -ForegroundColor:Red $global:responsebody
Write-Host -BackgroundColor:Black -ForegroundColor:Red "The request body has been saved to `$global:helpme"
break
}
然后,像这样将所有 Invoke-RestMethod 调用包装在一个 try Catch 块中。
try {
$e = Invoke-WebRequest 'https://api.us.onelogin.com/api/1/users/$id' `
-Headers @{ Authorization = "bearer:$token" } `
-Body ( @{ phone = "7709746046" } | ConvertTo-Json ) `
-Method Put `
-ErrorAction:Stop `
-ContentType 'application/json'
}
catch {Failure}
现在当您 运行 遇到错误时,您可以看到实际的消息,就像这样
> Status: A system exception was caught.
{"status":{"error":true,"code":400,"type":"bad request","message":{"description":"notes is not a valid attribute for user model","attribute":"notes"}}}
The request body has been saved to $global:helpme
这对帮助我摆脱遇到的错误非常有帮助,而且我能够使用 PUT
动词更新用户条目并使其正常工作。
正在解决您的问题
我只需要对您的代码进行两处更改即可使其正常工作。
首先,在 URI 周围加上引号,因为您的示例代码没有它们,您必须在哈希表中的字符串周围加上引号。
最后,将您的正文内容通过管道传输到 ConvertTo-JSON
,否则数据将作为字符串发送,就像您在 Fiddler 中发现的那样。
经过这两项更改,这是我的请求和响应
$Splat = @{
Method = 'PUT'
Uri = 'https://api.us.onelogin.com/api/1/users/27697924/add_roles'
ContentType = "application/json"
Headers = @{authorization = "bearer:$token" }
Body = @{role_id_array = @(143175)} | ConvertTo-Json
}
try {Invoke-RestMethod @Splat -ErrorAction Stop }
catch {Failure}
这是回复:
status
------
@{type=success; message=Success; error=False; code=200}
更新:我们做到了,现在已经修复了!
如果您认为 PowerShell 应该显示非 200 状态代码的实际服务器响应,请帮助提请注意 Github 上的这个 open issue on the PowerShell 项目页面。
添加您的反馈或竖起大拇指,我们可能会在该语言的未来版本中对此进行更改。
此问题现已从 PowerShell v6.1 开始修复
我正在使用 OneLogin REST API,似乎无法通过 PUT 方法进行任何调用。当我在 Postman 中测试时,我可以像这样传递一个原始的 JSON 正文:
{
"role_id_array": [
115028
]
}
到终点:
https://api.us.onelogin.com/api/1/users//add_roles
这很好用。但是,当我尝试对 PowerShell 的 Invoke-RestMethod 命令执行相同操作时,我收到 400 Bad Request 错误。我的代码如下所示:
$Splat = @{
Method = $Method
Uri = https://api.us.onelogin.com/api/1/users/12345678/add_roles
ContentType = "application/json"
Headers = @{authorization = "bearer:$($Token.access_token)"}
Body = @{role_id_array = @(123456)}
}
Invoke-RestMethod @Splat
到目前为止,我对任何 GET 调用都没有问题,只有 PUT 有问题。此外,如果我 运行 通过 ConvertTo-Json 传递的 Body 哈希表,输出看起来就像上面的工作示例。有没有人知道为什么这不起作用?
好的,所以我崩溃并安装了 Fiddler,我想我正在做点什么。 PowerShell cmdlet 似乎不知道如何处理 application/json 内容类型的数组。我不确定 XML 是否会出现这种情况,因为我还没有测试过。
我将主体更改为使用直 json 弦并且它有效:
$Body = "{ `"role_id_array`": [123456] }"
如果我使用哈希表并将值设置为这样的数组:
$Body = @{role_id_array = 115028,128732}
然后我会收到 400 失败响应。 Fiddler 向我展示了发生了什么——这是原始请求:
PUT https://api.us.onelogin.com/api/1/users/12345678/add_roles HTTP/1.1 授权:bearer:3c93ae2-编辑- 用户代理:Mozilla/5.0(Windows NT;Windows NT 6.3;en-US)WindowsPowerShell/5.1.14394.1000 内容类型:application/json 主持人:api.us.onelogin.com 内容长度:33 role_id_array=System.Object%5b%5d
请注意,数组未正确转换,Invoke-RestMethod 只是将其折叠成类型名称定义,类似于 Export-Csv 处理数组 属性 值的方式。
所以我认为我在使用 PUT 方法时遇到了问题,因为我的所有 GET 调用都在工作,但这是一个转移注意力的问题。真正的问题是处理一个 REST 端点,它需要数组值作为它的请求参数值。
编辑:我发现有人在 2014 年发布了这个问题,但他的解决方案是将 -ContentType 参数设置为 'application/json':
Powershell v4 Invoke-RestMethod body sends System.Object
我已经这样做了,但仍然遇到同样的问题。这是一个错误吗?
我能够 PUT
工作!
如何从 Invoke-RestMethod 获取丰富的错误响应数据
首先,我使用了 this blog post here,它有一个很好的方法来检索 Invoke-RestMethod
或 WebRequest
cmdlet 的完整错误消息。
在他的方法中,首先定义一个名为Failure的Function。
function Failure {
$global:helpme = $body
$global:helpmoref = $moref
$global:result = $_.Exception.Response.GetResponseStream()
$global:reader = New-Object System.IO.StreamReader($global:result)
$global:responseBody = $global:reader.ReadToEnd();
Write-Host -BackgroundColor:Black -ForegroundColor:Red "Status: A system exception was caught."
Write-Host -BackgroundColor:Black -ForegroundColor:Red $global:responsebody
Write-Host -BackgroundColor:Black -ForegroundColor:Red "The request body has been saved to `$global:helpme"
break
}
然后,像这样将所有 Invoke-RestMethod 调用包装在一个 try Catch 块中。
try {
$e = Invoke-WebRequest 'https://api.us.onelogin.com/api/1/users/$id' `
-Headers @{ Authorization = "bearer:$token" } `
-Body ( @{ phone = "7709746046" } | ConvertTo-Json ) `
-Method Put `
-ErrorAction:Stop `
-ContentType 'application/json'
}
catch {Failure}
现在当您 运行 遇到错误时,您可以看到实际的消息,就像这样
> Status: A system exception was caught.
{"status":{"error":true,"code":400,"type":"bad request","message":{"description":"notes is not a valid attribute for user model","attribute":"notes"}}}
The request body has been saved to $global:helpme
这对帮助我摆脱遇到的错误非常有帮助,而且我能够使用 PUT
动词更新用户条目并使其正常工作。
正在解决您的问题
我只需要对您的代码进行两处更改即可使其正常工作。
首先,在 URI 周围加上引号,因为您的示例代码没有它们,您必须在哈希表中的字符串周围加上引号。
最后,将您的正文内容通过管道传输到 ConvertTo-JSON
,否则数据将作为字符串发送,就像您在 Fiddler 中发现的那样。
经过这两项更改,这是我的请求和响应
$Splat = @{
Method = 'PUT'
Uri = 'https://api.us.onelogin.com/api/1/users/27697924/add_roles'
ContentType = "application/json"
Headers = @{authorization = "bearer:$token" }
Body = @{role_id_array = @(143175)} | ConvertTo-Json
}
try {Invoke-RestMethod @Splat -ErrorAction Stop }
catch {Failure}
这是回复:
status
------
@{type=success; message=Success; error=False; code=200}
更新:我们做到了,现在已经修复了!
如果您认为 PowerShell 应该显示非 200 状态代码的实际服务器响应,请帮助提请注意 Github 上的这个 open issue on the PowerShell 项目页面。
添加您的反馈或竖起大拇指,我们可能会在该语言的未来版本中对此进行更改。
此问题现已从 PowerShell v6.1 开始修复