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

I am trying to access a URL with a character /in it from powershell using the following command (this is a request to the gitlab server to get a project called "foo/bar"):

Invoke-WebRequest https://server.com/api/v3/projects/foo%2Fbar -Verbose

Now it’s strange that using PowerShell ISE or Visual Studio, the request is fine. When using PowerShell itself, the URL is not automatically activated, and the request fails. For instance.

In ISE / VS:

$> Invoke-WebRequest https://server.com/api/v3/projects/foo%2Fbar -Verbose
VERBOSE: GET https://server.com/api/v3/projects/foo%2Fbar with 0-byte payload
VERBOSE: received 19903-byte response of content type application/json

StatusCode        : 200
StatusDescription : OK
Content           : .... data ....

In Powershell:

$> Invoke-WebRequest https://server.com/api/v3/projects/foo%2Fbar -Verbose
VERBOSE: GET https://server.com/api/v3/projects/foo/bar with 0-byte payload
Invoke-WebRequest : {"error":"404 Not Found"}
At line:1 char:1
+ Invoke-WebRequest 'https://server.com/api/v3/projects/foo%2Fbar ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

I tried adding single and double quotes around the url but nothing helps.

What could be causing this behavior, and how to make PS not delete the URL string?


Environment: Windows 7, also tested on a 2012R2 server with the same results.

$> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.42000
BuildVersion                   6.3.9600.16406
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2
+6
4

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);
}

$uri = New-Object System.Uri -ArgumentList ("https://server.com/api/v3/projects/foo%2Fbar")
fixuri $uri
+10

PowerShell 5.1. , Git Lab Web API. Web API:


, NAMESPACE/PROJECT_NAME, . , , NAMESPACE/PROJECT_NAME URL, . /api/v 3/projects/diaspora% 2Fdiaspora (/% 2F).

NIK , Invoke-WebRequest , , Job. :

Start-Job -ScriptBlock {
    try{
        Invoke-WebRequest https://server.com/api/v3/projects/foo%2Fbar -verbose
    } catch {
        Write-Output $_.Exception
    }
}

. :

> Get-Job | Receive-Job -Keep

, :

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()

Oleg SH . . , Start-Job


: Windows 7
>$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
0

fooobar.com/questions/92307/... - 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
}

:

$uri = CreateUriWithoutIncorrectSlashEncoding "https://server.com/api/v3/projects/foo%2Fbar"
0

, PowerShell 5, , Uri, , , , ...

Invoke-RestMethod ([uri]"https://server.com/api/v3/projects/foo%2Fbar")
-1

Source: https://habr.com/ru/post/1673653/


All Articles