如果 URI 包含 URL 编码值,则使用 Powershell 调用-RestMethod 的团队城市生成步骤将失败



我在TeamCity中有一个构建步骤,它发送一个HTTP请求,如下所示:

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Token", "%TOKEN%")
$uri = 'https://host/apps/branches/%BRANCH_NAME%/builds'
$response = Invoke-RestMethod $uri -Method 'GET' -Headers $headers
Write-Host "##teamcity[setParameter name='url' value='$uri']"

%BRANCH_NAME%实际包含简单的分支名称时,它可以完美运行,例如' master', 'beta', 'dev'.

但是当%BRANCH_NAME%release%2F2019-DEC时,它的效果就不是很好了(URL编码值为release/2019-DEC(

我在本地Powershell上尝试了相同的脚本,它运行完美,但是当我将其作为TeamCity构建步骤运行时,我收到以下错误:

Invoke-RestMethod : The remote server returned an error: (404) Not Found.
At C:TeamCityBuildAgent4tempbuildTmppowershell7367326510068615884.ps1:5 char:13
+ $response = Invoke-RestMethod $uri -Method 'GET' -Headers $headers
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc 
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
##teamcity[setParameter name='url' value='https://host/app/branches/release%2F2019-DEC/']

我试图使用额外的 % 符号来转义百分号,如在 TeamCity 构建脚本中使用百分号,但不幸的是,它返回了相同的错误。

有什么想法吗?

已解决:

看似问题是由代理上的旧版本的 PowerShell 引起的,如果 URI 包含 URL 编码值,则导致团队城市构建步骤中描述的行为失败,Powershell Invoke-RestMethod 失败

这意味着实际上不需要额外的百分号,我们可以在脚本中对值进行 URL 编码。

所以最终版本将如下所示:

function fixuri($uri){
$UnEscapeDotsAndSlashes = 0x2000000;
$SimpleUserSyntax = 0x20000;
$type = $uri.GetType();
$fieldInfo = $type.GetField("m_Syntax", ([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic));
$uriParser = $fieldInfo.GetValue($uri);
$typeUriParser = $uriParser.GetType().BaseType;
$fieldInfo = $typeUriParser.GetField("m_Flags", ([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::FlattenHierarchy));
$uriSyntaxFlags = $fieldInfo.GetValue($uriParser);
$uriSyntaxFlags = $uriSyntaxFlags -band (-bnot $UnEscapeDotsAndSlashes);
$uriSyntaxFlags = $uriSyntaxFlags -band (-bnot $SimpleUserSyntax);
$fieldInfo.SetValue($uriParser, $uriSyntaxFlags);
}
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("X-API-Token", "%TOKEN%")
$branch = [System.Web.HttpUtility]::UrlEncode('release/2019-DEC1')
$uri = New-Object System.Uri -ArgumentList ("https://host/apps/branches/$branch")
fixuri $uri
$response = Invoke-RestMethod $uri -Method 'GET' -Headers $headers

特别感谢@Peska

相关内容

最新更新