Powershell - Invoke-WebRequest to a URL with literal '/' (%2F) in it Powershell - Invoke-WebRequest to a URL with literal '/' (%2F) in it powershell powershell

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