Powershell - Invoke-WebRequest to a URL with literal '/' (/) in it

前端 未结 3 1393
半阙折子戏
半阙折子戏 2021-02-15 11:53

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

相关标签:
3条回答
  • 2021-02-15 12:26

    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


    Environment: 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 讨论(0)
  • 2021-02-15 12:37

    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
    
    0 讨论(0)
  • 2021-02-15 12:47

    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"
    
    0 讨论(0)
提交回复
热议问题