【问题标题】:Powershell Invoke-RestMethod from VSTS build step fails with error 417VSTS 构建步骤中的 Powershell Invoke-RestMethod 失败并出现错误 417
【发布时间】:2018-02-16 09:52:31
【问题描述】:

我们给自己买了一个 Lametric 时钟 (www.lametric.com),它支持显示通过 Web-API 发送给它的消息。我们希望将其集成到我们的 CI/CD 队列中。为此,我们编写了一个 Powershell 脚本,它将发送指定的通知。该脚本在本地执行时工作正常。从(本地)VSTS Build Agent 执行时,它会失败并返回状态码 417。

这是 powershell 脚本:

Param (
    [Parameter(mandatory=$true)]
    [string] $BuildName,
    [Parameter(mandatory=$false)]
    [string] $Message
)


$Payload = '{"priority":"critical","icon_type":"alert","lifeTime":2000,"model":{"frames":[{"icon":"555","text":"' + $BuildName + ' BUILD FAILED! ' + $Message + '"}],"sound":{"category":"alarms","id":"alarm6","repeat":2},"cycles":0}}'

$request = @{uri = 'http://<ip-address>:8080/api/v2/device/notifications';
              Method = 'POST';
              Headers = @{Authorization = 'Basic <base64-encoded-credentials>='; "Content-Type" = 'application/json' }
       Body = $Payload
  }

invoke-restmethod @request

谁能指出我们正确的方向,为什么我们在构建步骤中遇到这个问题,而不是在本地?

更新 1:

如果我去掉所有变量,它仍然会失败。

更新 2:

  • Invoke-RestMethod 更改为 Invoke-WebRequest 并没有什么不同。
  • 调用GET 请求有效
  • 调用 POST 请求失败并出现错误 417

【问题讨论】:

  • 回到调试,我想……如果您从脚本中删除各种变量并执行最基本的脚本版本会发生什么?
  • 另外,你的标题是Invoke-WebRequest,但你的代码使用的是Invoke-RestMethod...仅供参考;-)
  • @gvee 感谢您了解这一点;)
  • 错误响应中有详细信息吗? 417 是期望失败,因此您可以随时尝试调整 Expect 标头。但是服务器可能完全(ab)将该代码用于其他目的。
  • 感谢@gvee 关于Invoke-WebRequestInvoke-RestMethod 的初步意见。我在下面发布了我的工作解决方案。

标签: powershell azure-pipelines-build-task lametric


【解决方案1】:

看来我找到了解决问题的方法。看到发送带有选项-UseBasicParsingGET 请求工作正常,我尝试将这两个请求一个接一个地组合起来。如果它们在两个单独的构建步骤中,这不起作用。

但是,一旦我发送了一个GET 请求并跟进上面提到的POST 请求,它就神奇地起作用了。我不知道为什么会这样,但这是我们目前的解决方案:

Param (
        [Parameter(mandatory=$true)]
        [string] $BuildName,
        [Parameter(mandatory=$false)]
        [string] $Message
)

$request = @{uri = 'http://<ip-address>:8080/api/v2';
            Method = 'GET';
            Headers = @{Authorization = 'Basic <base64-encoded-credentials>'; }
  }

invoke-webrequest -UseBasicParsing @request

$Payload = '{"priority":"critical","icon_type":"alert","lifeTime":2000,"model":{"frames":[{"icon":"555","text":"' + $BuildName + ' BUILD FAILED! ' + $Message + '"}],"sound":{"category":"alarms","id":"alarm6","repeat":2},"cycles":0}}'

$request = @{uri = 'http://<ip-address>:8080/api/v2/device/notifications';
            Method = 'POST';
            Headers = @{Authorization = 'Basic <base64-encoded-credentials>'; "Content-Type" = 'application/json' }
            Body = $Payload
  }

invoke-webrequest -UseBasicParsing @request

【讨论】:

  • @MarinaLiu-MSFT 感谢您的提醒。忘记设置 48 小时结束时的自动提醒。
  • 您好,我尝试了您的代码,但它不适用于我的 lametric 任何机会您可以解释如何让它工作。我用我的 lametrics IP 替换了 ,其中 = 我使用了$Text = 'dev:my api key' $Bytes = [System.Text.Encoding]::Unicode.GetBytes($Text) $EncodedText =[Convert]::ToBase64String($Bytes) $EncodedText 来获取编码的凭据,但它一直以invoke-webrequest : { "errors":[ { "message":"Authorization is required" } ] } 失败
  • @justinf 您可以使用 Postman 等工具创建 base64 编码字符串。您不应该对该内联进行编码。
  • 或者您可以使用类似base64encode.org 的网站,您可以在其中粘贴您的凭据(dev:)并对其进行编码。
  • 谢谢,我使用 base64encode.org 来获取字符串应该是什么,它可以工作,然后我像这样使用 powershell 来获得相同的结果$API = 'dev:exampl3415';$APIB = [System.Text.Encoding]::UTF8.GetBytes("$API");$API64B = [System.Convert]::ToBase64String($APIB) 现在可以工作了。我想问你有没有关于如何删除/关闭警报的 powershell 示例。我想不出那个。
猜你喜欢
  • 1970-01-01
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 2015-11-27
  • 1970-01-01
相关资源
最近更新 更多