From 4ad575b928a0bdf39ccfcd7772d646b9cefd2005 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sat, 7 Jan 2023 15:39:27 +0100 Subject: [PATCH 01/15] fix bug with managing redirection --- .../utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index e82bd7e5772..c9bfbeb4809 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1313,7 +1313,9 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM _cancelToken = new CancellationTokenSource(); response = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, _cancelToken.Token).GetAwaiter().GetResult(); - if (keepAuthorization && IsRedirectCode(response.StatusCode) && response.Headers.Location is not null) + bool sessionRedirect = WebSession.MaximumRedirection > 0 || WebSession.MaximumRedirection == -1; + + if (keepAuthorization && sessionRedirect && IsRedirectCode(response.StatusCode) && response.Headers.Location is not null) { _cancelToken.Cancel(); _cancelToken = null; From a1671df522d0ac9624fc5beae5c7b215e20495e4 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sun, 8 Jan 2023 00:48:39 +0100 Subject: [PATCH 02/15] Update src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs Co-authored-by: xtqqczze <45661989+xtqqczze@users.noreply.github.com> --- .../utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index c9bfbeb4809..4a0cd191f7b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1313,9 +1313,10 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM _cancelToken = new CancellationTokenSource(); response = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, _cancelToken.Token).GetAwaiter().GetResult(); - bool sessionRedirect = WebSession.MaximumRedirection > 0 || WebSession.MaximumRedirection == -1; - - if (keepAuthorization && sessionRedirect && IsRedirectCode(response.StatusCode) && response.Headers.Location is not null) + if (keepAuthorization + && WebSession.MaximumRedirection is not 0 + && IsRedirectCode(response.StatusCode) + && response.Headers.Location is not null) { _cancelToken.Cancel(); _cancelToken = null; From 8510729e91dd07cb66517369037c4f3c07c72370 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sun, 8 Jan 2023 02:14:56 +0100 Subject: [PATCH 03/15] keepAuthorization --> keepAuthorizationOnRedirect --- .../WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 4a0cd191f7b..4c0e88749b1 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1313,7 +1313,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM _cancelToken = new CancellationTokenSource(); response = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, _cancelToken.Token).GetAwaiter().GetResult(); - if (keepAuthorization + if (keepAuthorizationOnRedirect && WebSession.MaximumRedirection is not 0 && IsRedirectCode(response.StatusCode) && response.Headers.Location is not null) @@ -1340,7 +1340,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM using (client = GetHttpClient(handleRedirect: true)) using (HttpRequestMessage redirectRequest = GetRequest(currentUri)) { - response = GetResponse(client, redirectRequest, keepAuthorization); + response = GetResponse(client, redirectRequest, keepAuthorizationOnRedirect); } } @@ -1378,7 +1378,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM WriteVerbose(reqVerboseMsg); - return GetResponse(client, requestWithoutRange, keepAuthorization); + return GetResponse(client, requestWithoutRange, keepAuthorizationOnRedirect); } } @@ -1454,12 +1454,12 @@ protected override void ProcessRecord() // if the request contains an authorization header and PreserveAuthorizationOnRedirect is not set, // it needs to be stripped on the first redirect. - bool keepAuthorization = WebSession is not null && + bool keepAuthorizationOnRedirect = WebSession is not null && WebSession.Headers is not null && PreserveAuthorizationOnRedirect.IsPresent && WebSession.Headers.ContainsKey(HttpKnownHeaderNames.Authorization); - using (HttpClient client = GetHttpClient(keepAuthorization)) + using (HttpClient client = GetHttpClient(keepAuthorizationOnRedirect)) { int followedRelLink = 0; Uri uri = Uri; From e378ef2f887d2f49066329dbb3ff7a0e450125ab Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sun, 8 Jan 2023 02:16:24 +0100 Subject: [PATCH 04/15] remove useless IsPresent --- .../Common/WebRequestPSCmdlet.Common.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 4c0e88749b1..6754910bc9a 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -533,7 +533,7 @@ internal virtual void ValidateParameters() } // Resume requires OutFile. - if (Resume.IsPresent && OutFile is null) + if (Resume && OutFile is null) { ErrorRecord error = GetValidationError(WebCmdletStrings.OutFileMissing, "WebCmdletOutFileMissingException", nameof(Resume)); ThrowTerminatingError(error); @@ -666,7 +666,7 @@ internal virtual void PrepareSession() /// /// Determines whether writing to a file should Resume and append rather than overwrite. /// - internal bool ShouldResume => Resume.IsPresent && _resumeSuccess; + internal bool ShouldResume => Resume && _resumeSuccess; #endregion Helper Properties @@ -1102,7 +1102,7 @@ internal virtual HttpRequestMessage GetRequest(Uri uri) // If the file to resume downloading exists, create the Range request header using the file size. // If not, create a Range to request the entire file. - if (Resume.IsPresent) + if (Resume) { var fileInfo = new FileInfo(QualifiedOutFile); if (fileInfo.Exists) @@ -1347,7 +1347,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM // Request again without the Range header because the server indicated the range was not satisfiable. // This happens when the local file is larger than the remote file. // If the size of the remote file is the same as the local file, there is nothing to resume. - if (Resume.IsPresent && + if (Resume && response.StatusCode == HttpStatusCode.RequestedRangeNotSatisfiable && (response.Content.Headers.ContentRange.HasLength && response.Content.Headers.ContentRange.Length != _resumeFileSize)) @@ -1455,9 +1455,9 @@ protected override void ProcessRecord() // if the request contains an authorization header and PreserveAuthorizationOnRedirect is not set, // it needs to be stripped on the first redirect. bool keepAuthorizationOnRedirect = WebSession is not null && - WebSession.Headers is not null && - PreserveAuthorizationOnRedirect.IsPresent && - WebSession.Headers.ContainsKey(HttpKnownHeaderNames.Authorization); + WebSession.Headers is not null && + PreserveAuthorizationOnRedirect && + WebSession.Headers.ContainsKey(HttpKnownHeaderNames.Authorization); using (HttpClient client = GetHttpClient(keepAuthorizationOnRedirect)) { @@ -1508,7 +1508,7 @@ WebSession.Headers is not null && // Check if the Resume range was not satisfiable because the file already completed downloading. // This happens when the local file is the same size as the remote file. - if (Resume.IsPresent && + if (Resume && response.StatusCode == HttpStatusCode.RequestedRangeNotSatisfiable && response.Content.Headers.ContentRange.HasLength && response.Content.Headers.ContentRange.Length == _resumeFileSize) From 2a9f14741ef1dfe1298b9295e885d3124806b904 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sun, 8 Jan 2023 02:21:44 +0100 Subject: [PATCH 05/15] missed two keepAuthorizationOnRedirect --- .../utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 6754910bc9a..2772d6c78ec 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1294,7 +1294,7 @@ private bool ShouldRetry(HttpStatusCode code) ); } - internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestMessage request, bool keepAuthorization) + internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestMessage request, bool keepAuthorizationOnRedirect) { ArgumentNullException.ThrowIfNull(client); @@ -1493,7 +1493,7 @@ WebSession.Headers is not null && WriteVerbose(reqVerboseMsg); - HttpResponseMessage response = GetResponse(client, request, keepAuthorization); + HttpResponseMessage response = GetResponse(client, request, keepAuthorizationOnRedirect); string contentType = ContentHelper.GetContentType(response); string respVerboseMsg = string.Format( From f5b6d1df53d88cf02e33a353db59eb25b0bddfb7 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sun, 8 Jan 2023 02:28:07 +0100 Subject: [PATCH 06/15] bool handleRedirect = keepAuthorizationOnRedirect --- .../WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 2772d6c78ec..1dc2fc27bc7 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1313,7 +1313,9 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM _cancelToken = new CancellationTokenSource(); response = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, _cancelToken.Token).GetAwaiter().GetResult(); - if (keepAuthorizationOnRedirect + bool handleRedirect = keepAuthorizationOnRedirect; // || AllowInsicureRedirect || PreserveHTTPMethodOnRedirect + + if (handleRedirect && WebSession.MaximumRedirection is not 0 && IsRedirectCode(response.StatusCode) && response.Headers.Location is not null) @@ -1337,7 +1339,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM currentUri = new Uri(request.RequestUri, response.Headers.Location); // Continue to handle redirection - using (client = GetHttpClient(handleRedirect: true)) + using (client = GetHttpClient(handleRedirect)) using (HttpRequestMessage redirectRequest = GetRequest(currentUri)) { response = GetResponse(client, redirectRequest, keepAuthorizationOnRedirect); @@ -1459,7 +1461,9 @@ WebSession.Headers is not null && PreserveAuthorizationOnRedirect && WebSession.Headers.ContainsKey(HttpKnownHeaderNames.Authorization); - using (HttpClient client = GetHttpClient(keepAuthorizationOnRedirect)) + bool handleRedirect = keepAuthorizationOnRedirect; // || AllowInsicureRedirect || PreserveHTTPMethodOnRedirect + + using (HttpClient client = GetHttpClient(handleRedirect)) { int followedRelLink = 0; Uri uri = Uri; From e48bd3913b339b4791cf6e41de14c05c20f3998c Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sun, 8 Jan 2023 02:34:29 +0100 Subject: [PATCH 07/15] better handleRedirect if logic --- .../WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 1dc2fc27bc7..845296dd3dc 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -968,20 +968,13 @@ internal virtual HttpClient GetHttpClient(bool handleRedirect) } // This indicates GetResponse will handle redirects. - if (handleRedirect) + if (handleRedirect || WebSession.MaximumRedirection == 0) { handler.AllowAutoRedirect = false; } - else if (WebSession.MaximumRedirection > -1) + else if (WebSession.MaximumRedirection > 0) { - if (WebSession.MaximumRedirection == 0) - { - handler.AllowAutoRedirect = false; - } - else - { - handler.MaxAutomaticRedirections = WebSession.MaximumRedirection; - } + handler.MaxAutomaticRedirections = WebSession.MaximumRedirection; } handler.SslProtocols = (SslProtocols)SslProtocol; From 1345784d0156e1f49ac1929ff6cf64fe5c453812 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sun, 8 Jan 2023 13:12:12 +0100 Subject: [PATCH 08/15] revert Resume.IsPresent --- .../WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 845296dd3dc..f5596a2ad36 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -533,7 +533,7 @@ internal virtual void ValidateParameters() } // Resume requires OutFile. - if (Resume && OutFile is null) + if (Resume.IsPresent && OutFile is null) { ErrorRecord error = GetValidationError(WebCmdletStrings.OutFileMissing, "WebCmdletOutFileMissingException", nameof(Resume)); ThrowTerminatingError(error); @@ -666,7 +666,7 @@ internal virtual void PrepareSession() /// /// Determines whether writing to a file should Resume and append rather than overwrite. /// - internal bool ShouldResume => Resume && _resumeSuccess; + internal bool ShouldResume => Resume.IsPresent && _resumeSuccess; #endregion Helper Properties @@ -1095,7 +1095,7 @@ internal virtual HttpRequestMessage GetRequest(Uri uri) // If the file to resume downloading exists, create the Range request header using the file size. // If not, create a Range to request the entire file. - if (Resume) + if (Resume.IsPresent) { var fileInfo = new FileInfo(QualifiedOutFile); if (fileInfo.Exists) @@ -1342,7 +1342,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM // Request again without the Range header because the server indicated the range was not satisfiable. // This happens when the local file is larger than the remote file. // If the size of the remote file is the same as the local file, there is nothing to resume. - if (Resume && + if (Resume.IsPresent && response.StatusCode == HttpStatusCode.RequestedRangeNotSatisfiable && (response.Content.Headers.ContentRange.HasLength && response.Content.Headers.ContentRange.Length != _resumeFileSize)) @@ -1505,7 +1505,7 @@ WebSession.Headers is not null && // Check if the Resume range was not satisfiable because the file already completed downloading. // This happens when the local file is the same size as the remote file. - if (Resume && + if (Resume.IsPresent && response.StatusCode == HttpStatusCode.RequestedRangeNotSatisfiable && response.Content.Headers.ContentRange.HasLength && response.Content.Headers.ContentRange.Length == _resumeFileSize) From 3ed7bd71db7fef87f129eb6ec9c0762576976f4b Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Sun, 8 Jan 2023 13:18:09 +0100 Subject: [PATCH 09/15] keepAuthorizationOnRedirect --> handleRedirect --- .../WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index f5596a2ad36..729664cab7f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1287,7 +1287,7 @@ private bool ShouldRetry(HttpStatusCode code) ); } - internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestMessage request, bool keepAuthorizationOnRedirect) + internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestMessage request, bool handleRedirect) { ArgumentNullException.ThrowIfNull(client); @@ -1306,8 +1306,6 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM _cancelToken = new CancellationTokenSource(); response = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, _cancelToken.Token).GetAwaiter().GetResult(); - bool handleRedirect = keepAuthorizationOnRedirect; // || AllowInsicureRedirect || PreserveHTTPMethodOnRedirect - if (handleRedirect && WebSession.MaximumRedirection is not 0 && IsRedirectCode(response.StatusCode) @@ -1335,7 +1333,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM using (client = GetHttpClient(handleRedirect)) using (HttpRequestMessage redirectRequest = GetRequest(currentUri)) { - response = GetResponse(client, redirectRequest, keepAuthorizationOnRedirect); + response = GetResponse(client, redirectRequest, handleRedirect); } } @@ -1373,7 +1371,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM WriteVerbose(reqVerboseMsg); - return GetResponse(client, requestWithoutRange, keepAuthorizationOnRedirect); + return GetResponse(client, requestWithoutRange, handleRedirect); } } @@ -1490,7 +1488,7 @@ WebSession.Headers is not null && WriteVerbose(reqVerboseMsg); - HttpResponseMessage response = GetResponse(client, request, keepAuthorizationOnRedirect); + HttpResponseMessage response = GetResponse(client, request, handleRedirect); string contentType = ContentHelper.GetContentType(response); string respVerboseMsg = string.Format( From c2d3399c663c265e830c3866fcd3d6cabc1b38f1 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Wed, 11 Jan 2023 19:25:41 +0100 Subject: [PATCH 10/15] add test --- .../WebCmdlets.Tests.ps1 | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 0a84f60cd76..93156097cd1 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -133,14 +133,22 @@ function ExecuteRedirectRequest { $Method = 'GET', [switch] - $PreserveAuthorizationOnRedirect + $PreserveAuthorizationOnRedirect, + + [ValidateRange(0, [int]::MaxValue)] + [int] + $MaximumRedirection ) $result = [PSObject]@{Output = $null; Error = $null; Content = $null} try { $headers = @{"Authorization" = "test"} if ($Cmdlet -eq 'Invoke-WebRequest') { - $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method + if ($MaximumRedirection) { + $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method -MaximumRedirection:$MaximumRedirection + } else { + $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method + } $result.Content = $result.Output.Content | ConvertFrom-Json } else { $result.Output = Invoke-RestMethod -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method @@ -863,6 +871,14 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { $response.Error | Should -BeNullOrEmpty $response.Content.Headers."Authorization" | Should -BeExactly "test" } + + It "Validates Invoke-WebRequest with -PreserveAuthorizationOnRedirect respects -MaximumRedirection on redirect: " -TestCases $redirectTests { + param($redirectType, $redirectedMethod) + $uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3' -Query @{type = $redirectType} + $response = ExecuteRedirectRequest -Uri $uri -PreserveAuthorizationOnRedirect -MaximumRedirection 2 + + $response.Error.FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" + } It "Validates Invoke-WebRequest preserves the authorization header on multiple redirects: " -TestCases $redirectTests { param($redirectType) From c4ed1b714e4e95ed052da7aabc8dee2705fc8bfd Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Thu, 12 Jan 2023 09:46:46 +0100 Subject: [PATCH 11/15] Update test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 Co-authored-by: Ilya --- .../Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 93156097cd1..d9b3136bda6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -144,7 +144,7 @@ function ExecuteRedirectRequest { try { $headers = @{"Authorization" = "test"} if ($Cmdlet -eq 'Invoke-WebRequest') { - if ($MaximumRedirection) { + if ($MaximumRedirection -gt 0) { $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method -MaximumRedirection:$MaximumRedirection } else { $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method From 7f5b29812f60ffd72b22aaf8ce7cad55e1f25120 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Thu, 12 Jan 2023 10:02:48 +0100 Subject: [PATCH 12/15] Update src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs Co-authored-by: Ilya --- .../utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 729664cab7f..bc7114ea5f4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1449,7 +1449,7 @@ protected override void ProcessRecord() // it needs to be stripped on the first redirect. bool keepAuthorizationOnRedirect = WebSession is not null && WebSession.Headers is not null && - PreserveAuthorizationOnRedirect && + PreserveAuthorizationOnRedirect.IsPresent && WebSession.Headers.ContainsKey(HttpKnownHeaderNames.Authorization); bool handleRedirect = keepAuthorizationOnRedirect; // || AllowInsicureRedirect || PreserveHTTPMethodOnRedirect From 7f3fd07f47311639587b9a7f6bbad50dbee3248e Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Thu, 12 Jan 2023 11:38:29 +0100 Subject: [PATCH 13/15] remove comment --- .../utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index bc7114ea5f4..94f846e3770 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1452,7 +1452,7 @@ WebSession.Headers is not null && PreserveAuthorizationOnRedirect.IsPresent && WebSession.Headers.ContainsKey(HttpKnownHeaderNames.Authorization); - bool handleRedirect = keepAuthorizationOnRedirect; // || AllowInsicureRedirect || PreserveHTTPMethodOnRedirect + bool handleRedirect = keepAuthorizationOnRedirect; using (HttpClient client = GetHttpClient(handleRedirect)) { From 277145766cc847b06f9f385710be1372e6ed68ce Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Thu, 12 Jan 2023 18:12:01 +0100 Subject: [PATCH 14/15] reorder keepAuthorizationOnRedirect --- .../utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 082fc9f6f5d..61c032a13cf 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1416,10 +1416,8 @@ protected override void ProcessRecord() // If the request contains an authorization header and PreserveAuthorizationOnRedirect is not set, // it needs to be stripped on the first redirect. - bool keepAuthorizationOnRedirect = WebSession is not null - && WebSession.Headers is not null - && PreserveAuthorizationOnRedirect.IsPresent - && WebSession.Headers.ContainsKey(HttpKnownHeaderNames.Authorization); + bool keepAuthorizationOnRedirect = PreserveAuthorizationOnRedirect.IsPresent + && WebSession?.Headers?.ContainsKey(HttpKnownHeaderNames.Authorization); bool handleRedirect = keepAuthorizationOnRedirect || AllowInsecureRedirect; From 7a8daeb5c1eaec9f95da2137f4daafa42e6a811a Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Thu, 12 Jan 2023 18:22:16 +0100 Subject: [PATCH 15/15] fix error --- .../utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 61c032a13cf..3dcf289761a 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1417,7 +1417,7 @@ protected override void ProcessRecord() // If the request contains an authorization header and PreserveAuthorizationOnRedirect is not set, // it needs to be stripped on the first redirect. bool keepAuthorizationOnRedirect = PreserveAuthorizationOnRedirect.IsPresent - && WebSession?.Headers?.ContainsKey(HttpKnownHeaderNames.Authorization); + && WebSession.Headers.ContainsKey(HttpKnownHeaderNames.Authorization); bool handleRedirect = keepAuthorizationOnRedirect || AllowInsecureRedirect;