Powershell - Invoke-WebRequest to a URL with literal '/' (%2F) in it
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"
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 payloadSystem.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
Environment: Windows 7
>$PSVersionTableName Value---- -----PSVersion 5.1.14409.1005PSEdition DesktopPSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}BuildVersion 10.0.14409.1005CLRVersion 4.0.30319.42000WSManStackVersion 3.0PSRemotingProtocolVersion 2.3SerializationVersion 1.1.0.1