0
votes

I have a build step in TeamCity which sends an HTTP request, like this:

$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']"

It works perfectly when %BRANCH_NAME% actually contains simple branch names, like ' master', 'beta', 'dev'.

But it works not so good when %BRANCH_NAME% is release%2F2019-DEC (URL encoded value of release/2019-DEC)

I tried the same script on local Powershell, and it worked flawlessly, but when I run it as TeamCity build step I receive the following error:

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/']

I tried to escape the percent sign using the extra % sign as in Using the percent sign in TeamCity build scripts, but unfortunately, it returns the same error.

Any ideas?

1
Imho you should convert this other way around. Instead of using extra % sign, you should convert %2F to /. But this is just a hunch. Also you could check this solution: stackoverflow.com/a/43135803/7225096Peska
@Peska, thanks for your comment. The thing is that without URL encoding the target URI will be host/app/branches/release/2019-DEC, which will return 404 as there is no such resource. If you curl host/app/branches/release%2F2019-DEC it would work, the tricky thing is that it doesn't work in TeamCity. Thanks for the link, I'll take a look.n-verbitsky

1 Answers

0
votes

Solved:

Seemingly issue was caused by the old version of PowerShell on Agent, which caused the behavior described in Team City build step with Powershell Invoke-RestMethod fails if URI contains URL encoded value

That means that no extra percent signs are actually needed, we can URL encode value inside the script.

So the final version will look like:

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

Special thanks to @Peska