I have been trying to access a URL with a /
character in it from powershell, using the following command (it\'s a query to a gitlab server to retrieve a project ca
I have encountered similar issue in PowerShell 5.1. My purpose was to get a single project by Git Lab Web API. As Web API described:
Get single project
Get a specific project, identified by project ID or NAMESPACE/PROJECT_NAME , which is owned by the authentication user. If using namespaced projects call make sure that the NAMESPACE/PROJECT_NAME is URL-encoded, eg. /api/v3/projects/diaspora%2Fdiaspora (where / is represented by %2F).
What different with nik was that my Invoke-WebRequest call was successful by directly invoke but failed inside a Job. Here's the code:
Start-Job -ScriptBlock {
try{
Invoke-WebRequest https://server.com/api/v3/projects/foo%2Fbar -verbose
} catch {
Write-Output $_.Exception
}
}
To Get the output inside a Job. Run command:
> Get-Job | Receive-Job -Keep
And exception as below:
VERBOSE: GET https://server.com/api/v3/projects/foo/bar with 0-byte payload
System.Net.WebException: The remote server returned an error: (404) Not Found.
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
And thanks Oleg SH's answer. My problem was solved. But I think there might be a bug in the Start-Job cmdlet
>$PSVersionTable
Name Value
---- -----
PSVersion 5.1.14409.1005
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.14409.1005
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
Try the URL through this function
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);
}
$uri = New-Object System.Uri -ArgumentList ("https://server.com/api/v3/projects/foo%2Fbar")
fixuri $uri
Here is an alternate port of https://stackoverflow.com/a/784937/2864740 - it accepts a string and returns a new URI.
function CreateUriWithoutIncorrectSlashEncoding {
param(
[Parameter(Mandatory)][string]$uri
)
$newUri = New-Object System.Uri $uri
[void]$newUri.PathAndQuery # need to access PathAndQuery (presumably modifies internal state)
$flagsFieldInfo = $newUri.GetType().GetField("m_Flags", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
$flags = $flagsFieldInfo.GetValue($newUri)
$flags = $flags -band (-bnot 0x30) # remove Flags.PathNotCanonical|Flags.QueryNotCanonical (private enum)
$flagsFieldInfo.SetValue($newUri, $flags)
$newUri
}
Usage:
$uri = CreateUriWithoutIncorrectSlashEncoding "https://server.com/api/v3/projects/foo%2Fbar"