1

私は、PowerShell Core v6-beta.5をLinux上でAppImageを使用して使用しています。 301リダイレクトの「新しい」場所を見つける方法はありますか?Powershellは、永久に移動した(リダイレクトされた)リソースの新しいURLを決定します。

Invoke-WebRequest -Method HEAD http://SomethingThatThrows301.com/ -MaximumRedirection 0はエラー(Response status code does not indicate success: 301 (Moved Permanently))をスローします。

エラーには移動が301であることが記載されていますが、私にはまだそれと新しいアドレスを伝える適切なオブジェクトが必要です。

これを行う方法はありますか?

答えて

1

注:デフォルトでは、最大50リダイレクトでサポートされているすべてのプラットフォーム上の両方のWindows PowerShellPowerShellのコア作品以下のすべてのコード、。

と仮定すると:

  • あなたは特定の3xxリダイレクトステータスコードと
  • あなたが 究極ターゲットURLを知りたい
  • があるかもしれない気にしないことリダイレクトの

[System.Net.HttpWebRequest]::Create('http://cnn.com').GetResponse().ResponseUri.AbsoluteUri 

この利回り(ターゲットURLがwww.を持っているかに注意してください):以下

http://www.cnn.com 

は、両方の解像度を提供し、機能をパッケージ化し、高度な便利な機能Get-UrlRedirection、のソースコードです最終的なターゲットURLとリダイレクトURLの連鎖の列挙です。

例コール:

> Get-UrlRedirection http://cnn.com 
http://www.cnn.com 

> Get-UrlRedirection -Enumerate http://microsoft.com/about 
http://microsoft.com/about 
https://microsoft.com/about 
https://www.microsoft.com/about 
https://www.microsoft.com/about/ 
https://www.microsoft.com/about/default.aspx 
https://www.microsoft.com/en-us/about/ 

Function Get-UrlRedirection { 
    [CmdletBinding()] 
    Param (
    [Parameter(Mandatory, ValueFromPipeline)] [Uri] $Url, 
    [switch] $Enumerate, 
    [int] $MaxRedirections = 50 # Use same default as [System.Net.HttpWebRequest] 
) 

    process { 
    try { 

     if ($Enumerate) { # Enumerate the whole redirection chain, from input URL to ultimate target, 
         # assuming the max. count of redirects is not exceeded. 
     # We must walk the chain of redirections one by one. 
     # If we disallow redirections, .GetResponse() fails and we must examine 
     # the exception's .Response object to get the redirect target. 
     $nextUrl = $Url 
     $urls = @($nextUrl.AbsoluteUri) # Start with the input Uri 
     $ultimateFound = $false 
     # Note: We add an extra loop iteration so we can determine whether 
     #  the ultimate target URL was reached or not. 
     foreach($i in 1..$($MaxRedirections+1)) { 
      Write-Verbose "Examining: $nextUrl" 
      $request = [System.Net.HttpWebRequest]::Create($nextUrl) 
      $request.AllowAutoRedirect = $False 
      try { 
      $response = $request.GetResponse() 
      # Note: In .NET *Core* the .GetResponse() for a redirected resource 
      #  with .AllowAutoRedirect -eq $False throws an *exception*. 
      #  We only get here on *Windows*, with the full .NET Framework. 
      #  We either have the ultimate target URL, or a redirection 
      #  whose target URL is reflected in .Headers['Location'] 
      #  !! Syntax `.Headers.Location` does NOT work. 
      $nextUrlStr = $response.Headers['Location'] 
      $response.Close() 
      # If the ultimate target URL was reached (it was already 
      # recorded in the previous iteration), and if so, simply exit the loop. 
      if (-not $nextUrlStr) { 
       $ultimateFound = $true 
       break 
      } 
      } catch [System.Net.WebException] { 
      # The presence of a 'Location' header implies that the 
      # exception must have been triggered by a HTTP redirection 
      # status code (3xx). 
      # $_.Exception.Response.StatusCode contains the specific code 
      # (as an enumeration value that can be case to [int]), if needed. 
      # !! Syntax `.Headers.Location` does NOT work. 
      $nextUrlStr = try { $_.Exception.Response.Headers['Location'] } catch {} 
      # Not being able to get a target URL implies that an unexpected 
      # error ocurred: re-throw it. 
      if (-not $nextUrlStr) { Throw } 
      } 
      Write-Verbose "Raw target: $nextUrlStr" 
      if ($nextUrlStr -match '^https?:') { # absolute URL 
      $nextUrl = $prevUrl = [Uri] $nextUrlStr 
      } else { # URL without scheme and server component 
      $nextUrl = $prevUrl = [Uri] ($prevUrl.Scheme + '://' + $prevUrl.Authority + $nextUrlStr) 
      } 
      if ($i -le $MaxRedirections) { $urls += $nextUrl.AbsoluteUri }   
     } 
     # Output the array of URLs (chain of redirections) as a *single* object. 
     Write-Output -NoEnumerate $urls 
     if (-not $ultimateFound) { Write-Warning "Enumeration of $Url redirections ended before reaching the ultimate target." } 

     } else { # Resolve just to the ultimate target, 
       # assuming the max. count of redirects is not exceeded. 

       # Note that .AllowAutoRedirect defaults to $True. 
     # This will fail, if there are more redirections than the specified 
     # or default maximum. 
     $request = [System.Net.HttpWebRequest]::Create($Url) 
     if ($PSBoundParameters.ContainsKey('MaxRedirections')) { 
      $request.MaximumAutomaticRedirections = $MaxRedirections 
     } 
     $response = $request.GetResponse() 
     # Output the ultimate target URL. 
     # If no redirection was involved, this is the same as the input URL. 
     $response.ResponseUri.AbsoluteUri 
     $response.Close() 

     } 

     } catch { 
     Write-Error $_ # Report the exception as a non-terminating error. 
    } 
    } # process 

} 

コードに注力するためには、私は上記コメントベースのヘルプを省略しました。ここでは、関数定義のすぐ上に貼り付けます。

<# 
.SYNOPSIS 
Gets a URL's redirection target(s). 

.DESCRIPTION 
Given a URL, determines its redirection target(s), as indicated by responses 
with 3xx HTTP status codes. 

If the URL is not redirected, it is output as-is. 

By default, the ultimate target URL is determined (if there's a chain of 
redirections), but the number of redirections that are followed is limited 
to 50 by default, which you may change with -MaxRedirections. 

-Enumerate enumerates the redirection chain and returns an array of URLs. 

.PARAMETER Url 
The URL whose redirection target to determine. 
You may supply multiple URLs via the pipeline. 

.PARAMETER MaxRedirections 
Limits the number of redirections that are followed, 50 by default. 
If the limit is exceeded, a non-terminating error is reported. 

.PARAMETER Enumerate 
Enumerates the chain of redirections, if applicable, starting with 
the input URL itself, and outputs it as an array. 

If the number of actual redirections doesn't exceed the specified or default 
-MaxRedirections value, the entire chain up to the ultimate target URL is 
enumerated. 
Otherwise, a warning is issued to indicate that the ultimate target URL wasn't 
reached. 

All URLs are output in absolute form, even if the targets are defined as 
relative URLs. 

Note that, in order to support multiple input URLs via the pipeline, each 
array representing a redirection chain is output as a *single* object, so 
with multiple input URLs you'll get an array of arrays as output. 

.EXAMPLE 
> Get-UrlRedirection http://cnn.com 
http://www.cnn.com 

.EXAMPLE 
> Get-UrlRedirection -Enumerate http://microsoft.com/about 
http://microsoft.com/about 
https://microsoft.com/about 
https://www.microsoft.com/about 
https://www.microsoft.com/about/ 
https://www.microsoft.com/about/default.aspx 
https://www.microsoft.com/en-us/about/ 

.NOTES 
This function uses the [System.Net.HttpWebRequest] .NET class and was 
inspired by http://www.powershellmagazine.com/2013/01/29/pstip-retrieve-a-redirected-url/ 
#> 
1

スローされたエラーを無視すると、HTTP応答を調べることができます。新しいURLはLocationヘッダーに表示されます。

以下のように試してみてください。

$url="https://jigsaw.w3.org/HTTP/300/301.html" 
$resp = Invoke-WebRequest -Method HEAD $url -MaximumRedirection 0 -ErrorAction Ignore 
$code = $resp.StatusCode 
Write-Host "URL: $url" 
Write-Host "ErrorCode: $code" 
if($code -eq 301) { 
    $loc = $resp.Headers.Location 
    Write-Host "New URL: $loc" 
} 
+0

Hmm ..これは、PowerShell 6b5のAppImage on Archでは機能しません。 'resp.getType()' 'ヌル値の式でメソッドを呼び出すことはできません。 '助けてくれてありがとう。何か良いことがなければ私は待って答えにします。 – 0fnt

+1

これは_Windows PowerShell_でもうまく動作しますが、PowerShell _Core_(WindowsとUnixの両方)では動作が変更されています。[変更が意図的であったかどうか](https://github.com/PowerShell/PowerShell/issues/4534)、わかりません。脇に:(write-host'を避ける)ことが最善です(http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/)。 – mklement0

+1

また、リダイレクトが連鎖される可能性があるため、これは_immediate_リダイレクションURLを取得するだけで、_ultimate_ターゲットURLである場合とそうでない場合があります。さらに、リダイレクトがどのように定義されているかに応じて、結果は_relative_ URLになります。 – mklement0

関連する問題