You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Horizon REST-API复制应用池遇BAD_REQUEST错误求助

Horizon REST API 应用池复制出现BAD_REQUEST解析错误的排查方案

问题背景

尝试将源Horizon连接服务器(HCS)上的应用池复制到另一台服务器,实验室环境运行正常,但其他环境执行Invoke-RestMethod时遇到错误:"BAD_REQUEST The input request cannot be parsed"。所有环境均使用PowerShell 7.3.0、PowerCLI 13、Horizon 2111。

操作代码如下:
获取源应用池:

$horizonApps_source = Invoke-RestMethod -Method Get -uri "$RESTurl_source/rest/inventory/v2/application-pools" -ContentType "application/json" -Headers (Get-HRHeader -accessToken $accessToken_source)

复制到目标服务器:

If ($horizonApps_source -ne $null) {
    ForEach ($item in $horizonApps_source) {
        $jsonFile = $fileLoc + $item.Display_Name + ".json"
        $item = $item | Select-Object * -ExcludeProperty Id, access_group_id, icon_ids, customized_icon_ids
        $item.farm_id = $farmID_target
        $item | ConvertTo-Json -Depth 100 | Out-File $jsonFile
        $appJson = $item | ConvertTo-Json -Depth 100
        $app_target = Invoke-RestMethod -Method Post -uri "$RESTurl_target/rest/inventory/v2/application-pools" -ContentType "application/json" -Headers (Get-HRHeader -accessToken $accessToken_target) -body $appJson -SkipCertificateCheck
    }
}

生成的JSON文件格式看似正常,但目标HCS未创建应用池,错误信息:

Line |
   8 |  … pp_target = Invoke-RestMethod -Method Post -uri "$RESTurl_target/rest …
     |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | {"status":"BAD_REQUEST","timestamp":1670869477302,"error_message":"The input request cannot be parsed."}

可能的原因

  • 编码不兼容:PowerShell的ConvertTo-Json默认输出的字符串可能带BOM,或者Out-File用UTF-16LE编码保存,而Horizon API仅支持UTF-8无BOM格式,导致解析失败。
  • 冗余/不兼容字段残留:虽然排除了部分字段,但Get接口返回的其他元数据字段(如_links)或数据类型不匹配的字段(比如数字转字符串)可能被带入请求体,导致API无法解析。
  • Farm ID格式错误:$farmID_target可能存在大小写不一致、GUID格式错误,或者目标环境中不存在该Farm ID,触发解析失败。
  • 请求头格式问题:Get-HRHeader生成的Header可能缺少必要字段(如Accept),或Authorization令牌格式错误(比如缺少Bearer前缀),间接导致请求体解析异常。
  • PowerShell自动类型转换:Select-Object后某些空值被转为PowerShell的$null,但API期望JSON原生的null或完全省略该字段,引发解析错误。

详细错误捕获与定位方法

  • 用Invoke-WebRequest捕获完整请求细节:替代Invoke-RestMethod获取更全面的请求和响应信息,包括实际发送的请求体:
    try {
        $response = Invoke-WebRequest -Method Post -uri "$RESTurl_target/rest/inventory/v2/application-pools" -ContentType "application/json" -Headers (Get-HRHeader -accessToken $accessToken_target) -body $appJson -SkipCertificateCheck
    } catch {
        Write-Host "=== 调试信息 ==="
        Write-Host "请求体内容:`n$appJson"
        Write-Host "响应状态码:" $_.Exception.Response.StatusCode.value__
        Write-Host "响应详细信息:`n$($_.ErrorDetails.Message)"
        # 保存UTF-8无BOM格式的调试JSON
        $appJson | Out-File "$fileLoc/debug_$($item.Display_Name).json" -Encoding utf8NoBOM
    }
    
  • 验证JSON与API Schema匹配:将生成的$appJson复制到Horizon官方API的Swagger测试界面,检查是否符合接口的字段要求(必填项、数据类型、枚举值等)。
  • 强制UTF-8无BOM编码:确保请求体使用API兼容的编码:
    $appJson = $item | ConvertTo-Json -Depth 100
    # 转为UTF-8无BOM字节数组再转回字符串
    $utf8Encoder = [System.Text.UTF8Encoding]::new($false)
    $appJson = $utf8Encoder.GetString($utf8Encoder.GetBytes($appJson))
    
  • 逐步简化请求体:先构建仅包含必填字段的最小请求体测试,确认能成功创建应用池后,再逐步添加其他字段,定位到导致解析失败的具体字段。
  • 检查请求头完整性:输出Get-HRHeader返回的Header,确认格式正确:
    $header = Get-HRHeader -accessToken $accessToken_target
    Write-Host "请求头详情:`n$($header | ConvertTo-Json)"
    

内容的提问来源于stack exchange,提问作者ChrisTheTerror

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 19:10:28