我在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:\TeamCityBuildAgent4\temp\buildTmp\powershell7367326510068615884.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/']
我尝试使用Using the percent sign in TeamCity build scripts中的多余%符号对百分比符号进行转义,但不幸的是,它返回了相同的错误。
有什么想法吗?
答案 0 :(得分:0)
已解决:
看似问题是由Agent上旧版本的PowerShell引起的,该问题导致Team City build step with Powershell Invoke-RestMethod fails if URI contains URL encoded value
中描述的行为这意味着实际上不需要多余的百分号,我们可以在脚本内对值进行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