From eb6827f248a45c04f8964e57e83ead4ea2142727 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Mon, 8 May 2023 02:56:30 +0200 Subject: [PATCH 1/8] Add test for error 429 Retry-After --- .../WebCmdlets.Tests.ps1 | 20 +++++++++ .../Controllers/RetryController.cs | 42 ++++++++++++++++++- 2 files changed, 61 insertions(+), 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 2b2968ea3da..3f11fd4875f 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -2145,6 +2145,16 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { $jsonError.error | Should -BeExactly 'Error: HTTP - 400 occurred.' } + It "Invoke-WebRequest can retry - specified number of times following Retry-After header - error 429" { + + $uri = Get-WebListenerUrl -Test 'RetryAfter' -Query @{ sessionid = (New-Guid).Guid; failureCode = 409; failureCount = 2; retryAfter = 2 } + $verboseFile = Join-Path $TestDrive -ChildPath verbose.txt + $result = Invoke-WebRequest -Uri $uri -MaximumRetryCount 2 -RetryIntervalSec 1 -Verbose 4>>$verboseFile + + $result.StatusCode | Should -Be "200" + $verboseFile | Should -FileContentMatch "Retrying after interval of 2 seconds. Status code for previous attempt: Conflict" + } + It "Invoke-WebRequest can retry with POST" { $uri = Get-WebListenerUrl -Test 'Retry' @@ -4036,6 +4046,16 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { $result.output.sessionId | Should -BeExactly $sessionId } + It "Invoke-RestMethod can retry - specified number of times following Retry-After header - error 429" { + + $uri = Get-WebListenerUrl -Test 'RetryAfter' -Query @{ sessionid = (New-Guid).Guid; failureCode = 409; failureCount = 2; retryAfter = 2 } + $verboseFile = Join-Path $TestDrive -ChildPath verbose.txt + $result = Invoke-RestMethod -Uri $uri -MaximumRetryCount 2 -RetryIntervalSec 1 -Verbose 4>>$verboseFile + + $result.StatusCode | Should -Be "200" + $verboseFile | Should -FileContentMatch "Retrying after interval of 2 seconds. Status code for previous attempt: Conflict" + } + It "Invoke-RestMethod can retry with POST" { $uri = Get-WebListenerUrl -Test 'Retry' diff --git a/test/tools/WebListener/Controllers/RetryController.cs b/test/tools/WebListener/Controllers/RetryController.cs index f9f93bae4c0..13664357bab 100644 --- a/test/tools/WebListener/Controllers/RetryController.cs +++ b/test/tools/WebListener/Controllers/RetryController.cs @@ -21,10 +21,50 @@ public class RetryController : Controller // Dictionary for sessionId as key and failureCode, failureCount and failureResponsesSent as the value. private static Dictionary> retryInfo; - public JsonResult Retry(string sessionId, int failureCode, int failureCount) + public JsonResult Retry(string sessionId, int failureCode, int failureCount, int RetryAfter = null) { retryInfo ??= new Dictionary>(); + if (failureCode == 409 && RetryAfter != null) + { + Response.Headers.Append("Retry-After", $"{RetryAfter}"); + } + + if (retryInfo.TryGetValue(sessionId, out Tuple retry)) + { + // if failureResponsesSent is less than failureCount + if (retry.Item3 < retry.Item2) + { + Response.StatusCode = retry.Item1; + retryInfo[sessionId] = Tuple.Create(retry.Item1, retry.Item2, retry.Item3 + 1); + Hashtable error = new Hashtable { { "error", $"Error: HTTP - {retry.Item1} occurred." } }; + return Json(error); + } + else + { + retryInfo.Remove(sessionId); + + // echo back sessionId for POST test. + var resp = new Hashtable { { "failureResponsesSent", retry.Item3 }, { "sessionId", sessionId } }; + return Json(resp); + } + } + else + { + // initialize the failureResponsesSent as 1. + var newRetryInfoItem = Tuple.Create(failureCode, failureCount, 1); + retryInfo.Add(sessionId, newRetryInfoItem); + Response.StatusCode = failureCode; + Hashtable error = new Hashtable { { "error", $"Error: HTTP - {failureCode} occurred." } }; + return Json(error); + } + } + + public JsonResult RetryAfter(string sessionId, int failureCode, int failureCount, string RetryAfter) + { + retryInfo ??= new Dictionary>(); + Response.Headers.Append("Retry-After", RetryAfter); + if (retryInfo.TryGetValue(sessionId, out Tuple retry)) { // if failureResponsesSent is less than failureCount From 7077a5f1b5cbe49b2a5bc094ecdee3f8d8fe88a3 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Mon, 8 May 2023 03:06:11 +0200 Subject: [PATCH 2/8] fix Invoke-RestMethod test --- .../Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 | 1 - 1 file changed, 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 3f11fd4875f..dc5534fa1af 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -4052,7 +4052,6 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { $verboseFile = Join-Path $TestDrive -ChildPath verbose.txt $result = Invoke-RestMethod -Uri $uri -MaximumRetryCount 2 -RetryIntervalSec 1 -Verbose 4>>$verboseFile - $result.StatusCode | Should -Be "200" $verboseFile | Should -FileContentMatch "Retrying after interval of 2 seconds. Status code for previous attempt: Conflict" } From 9f2cfa8ce74c19995caf6ba701d8aee35918013c Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Mon, 8 May 2023 03:09:46 +0200 Subject: [PATCH 3/8] fix codefactor --- .../Controllers/RetryController.cs | 41 ++----------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/test/tools/WebListener/Controllers/RetryController.cs b/test/tools/WebListener/Controllers/RetryController.cs index 13664357bab..b6d5a90ee66 100644 --- a/test/tools/WebListener/Controllers/RetryController.cs +++ b/test/tools/WebListener/Controllers/RetryController.cs @@ -21,13 +21,13 @@ public class RetryController : Controller // Dictionary for sessionId as key and failureCode, failureCount and failureResponsesSent as the value. private static Dictionary> retryInfo; - public JsonResult Retry(string sessionId, int failureCode, int failureCount, int RetryAfter = null) + public JsonResult Retry(string sessionId, int failureCode, int failureCount, int retryAfter = null) { retryInfo ??= new Dictionary>(); - if (failureCode == 409 && RetryAfter != null) + if (failureCode == 409 && retryAfter != null) { - Response.Headers.Append("Retry-After", $"{RetryAfter}"); + Response.Headers.Append("Retry-After", $"{retryAfter}"); } if (retryInfo.TryGetValue(sessionId, out Tuple retry)) @@ -60,41 +60,6 @@ public JsonResult Retry(string sessionId, int failureCode, int failureCount, int } } - public JsonResult RetryAfter(string sessionId, int failureCode, int failureCount, string RetryAfter) - { - retryInfo ??= new Dictionary>(); - Response.Headers.Append("Retry-After", RetryAfter); - - if (retryInfo.TryGetValue(sessionId, out Tuple retry)) - { - // if failureResponsesSent is less than failureCount - if (retry.Item3 < retry.Item2) - { - Response.StatusCode = retry.Item1; - retryInfo[sessionId] = Tuple.Create(retry.Item1, retry.Item2, retry.Item3 + 1); - Hashtable error = new Hashtable { { "error", $"Error: HTTP - {retry.Item1} occurred." } }; - return Json(error); - } - else - { - retryInfo.Remove(sessionId); - - // echo back sessionId for POST test. - var resp = new Hashtable { { "failureResponsesSent", retry.Item3 }, { "sessionId", sessionId } }; - return Json(resp); - } - } - else - { - // initialize the failureResponsesSent as 1. - var newRetryInfoItem = Tuple.Create(failureCode, failureCount, 1); - retryInfo.Add(sessionId, newRetryInfoItem); - Response.StatusCode = failureCode; - Hashtable error = new Hashtable { { "error", $"Error: HTTP - {failureCode} occurred." } }; - return Json(error); - } - } - public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); From 4fa7a2d7f94d6119e17e4c2ed24492c7b99d0388 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Mon, 8 May 2023 03:19:14 +0200 Subject: [PATCH 4/8] fix error --- test/tools/WebListener/Controllers/RetryController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/tools/WebListener/Controllers/RetryController.cs b/test/tools/WebListener/Controllers/RetryController.cs index b6d5a90ee66..c22a5424a8d 100644 --- a/test/tools/WebListener/Controllers/RetryController.cs +++ b/test/tools/WebListener/Controllers/RetryController.cs @@ -21,13 +21,13 @@ public class RetryController : Controller // Dictionary for sessionId as key and failureCode, failureCount and failureResponsesSent as the value. private static Dictionary> retryInfo; - public JsonResult Retry(string sessionId, int failureCode, int failureCount, int retryAfter = null) + public JsonResult Retry(string sessionId, int failureCode, int failureCount, string retryAfter = null) { retryInfo ??= new Dictionary>(); if (failureCode == 409 && retryAfter != null) { - Response.Headers.Append("Retry-After", $"{retryAfter}"); + Response.Headers.Append("Retry-After", retryAfter); } if (retryInfo.TryGetValue(sessionId, out Tuple retry)) From c5351d13048736d1042d79ce07c5b5e2c38fb952 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Mon, 8 May 2023 03:27:43 +0200 Subject: [PATCH 5/8] fix error --- test/tools/WebListener/Controllers/RetryController.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/tools/WebListener/Controllers/RetryController.cs b/test/tools/WebListener/Controllers/RetryController.cs index c22a5424a8d..62339bb329d 100644 --- a/test/tools/WebListener/Controllers/RetryController.cs +++ b/test/tools/WebListener/Controllers/RetryController.cs @@ -21,13 +21,13 @@ public class RetryController : Controller // Dictionary for sessionId as key and failureCode, failureCount and failureResponsesSent as the value. private static Dictionary> retryInfo; - public JsonResult Retry(string sessionId, int failureCode, int failureCount, string retryAfter = null) + public JsonResult Retry(string sessionId, int failureCode, int failureCount, int retryAfter = 0) { retryInfo ??= new Dictionary>(); - if (failureCode == 409 && retryAfter != null) + if (failureCode == 409 && retryAfter > 0) { - Response.Headers.Append("Retry-After", retryAfter); + Response.Headers.Append("Retry-After", $"{retryAfter}"); } if (retryInfo.TryGetValue(sessionId, out Tuple retry)) From c0bb940f09b42211920a9137ba324e81d48d67ef Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Mon, 8 May 2023 03:37:52 +0200 Subject: [PATCH 6/8] add Microsoft.AspNetCore.Http --- test/tools/WebListener/Controllers/RetryController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/tools/WebListener/Controllers/RetryController.cs b/test/tools/WebListener/Controllers/RetryController.cs index 62339bb329d..9a617bb7314 100644 --- a/test/tools/WebListener/Controllers/RetryController.cs +++ b/test/tools/WebListener/Controllers/RetryController.cs @@ -9,6 +9,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; From 4c6f6e7931433b6bee890a12e037082840c2b95c Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Mon, 8 May 2023 03:52:27 +0200 Subject: [PATCH 7/8] fix --- .../Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 | 4 ++-- 1 file changed, 2 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 dc5534fa1af..615d6511eb9 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -2147,7 +2147,7 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { It "Invoke-WebRequest can retry - specified number of times following Retry-After header - error 429" { - $uri = Get-WebListenerUrl -Test 'RetryAfter' -Query @{ sessionid = (New-Guid).Guid; failureCode = 409; failureCount = 2; retryAfter = 2 } + $uri = Get-WebListenerUrl -Test 'Retry' -Query @{ sessionid = (New-Guid).Guid; failureCode = 409; failureCount = 2; retryAfter = 2 } $verboseFile = Join-Path $TestDrive -ChildPath verbose.txt $result = Invoke-WebRequest -Uri $uri -MaximumRetryCount 2 -RetryIntervalSec 1 -Verbose 4>>$verboseFile @@ -4048,7 +4048,7 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { It "Invoke-RestMethod can retry - specified number of times following Retry-After header - error 429" { - $uri = Get-WebListenerUrl -Test 'RetryAfter' -Query @{ sessionid = (New-Guid).Guid; failureCode = 409; failureCount = 2; retryAfter = 2 } + $uri = Get-WebListenerUrl -Test 'Retry' -Query @{ sessionid = (New-Guid).Guid; failureCode = 409; failureCount = 2; retryAfter = 2 } $verboseFile = Join-Path $TestDrive -ChildPath verbose.txt $result = Invoke-RestMethod -Uri $uri -MaximumRetryCount 2 -RetryIntervalSec 1 -Verbose 4>>$verboseFile From c158f608425f9b76550b8e0846953a411c334e19 Mon Sep 17 00:00:00 2001 From: CarloToso <105941898+CarloToso@users.noreply.github.com> Date: Mon, 8 May 2023 14:28:19 +0200 Subject: [PATCH 8/8] Modify tests to fail --- .../Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 | 8 ++++---- test/tools/WebListener/Controllers/RetryController.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 615d6511eb9..79aaf2f1033 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -2147,12 +2147,12 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { It "Invoke-WebRequest can retry - specified number of times following Retry-After header - error 429" { - $uri = Get-WebListenerUrl -Test 'Retry' -Query @{ sessionid = (New-Guid).Guid; failureCode = 409; failureCount = 2; retryAfter = 2 } + $uri = Get-WebListenerUrl -Test 'Retry' -Query @{ sessionid = (New-Guid).Guid; failureCode = 429; failureCount = 2; retryAfter = 2 } $verboseFile = Join-Path $TestDrive -ChildPath verbose.txt $result = Invoke-WebRequest -Uri $uri -MaximumRetryCount 2 -RetryIntervalSec 1 -Verbose 4>>$verboseFile $result.StatusCode | Should -Be "200" - $verboseFile | Should -FileContentMatch "Retrying after interval of 2 seconds. Status code for previous attempt: Conflict" + $verboseFile | Should -FileContentMatch "Retrying after interval of 2 seconds. Status code for previous attempt: TooManyRequests" } It "Invoke-WebRequest can retry with POST" { @@ -4048,11 +4048,11 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { It "Invoke-RestMethod can retry - specified number of times following Retry-After header - error 429" { - $uri = Get-WebListenerUrl -Test 'Retry' -Query @{ sessionid = (New-Guid).Guid; failureCode = 409; failureCount = 2; retryAfter = 2 } + $uri = Get-WebListenerUrl -Test 'Retry' -Query @{ sessionid = (New-Guid).Guid; failureCode = 429; failureCount = 2; retryAfter = 2 } $verboseFile = Join-Path $TestDrive -ChildPath verbose.txt $result = Invoke-RestMethod -Uri $uri -MaximumRetryCount 2 -RetryIntervalSec 1 -Verbose 4>>$verboseFile - $verboseFile | Should -FileContentMatch "Retrying after interval of 2 seconds. Status code for previous attempt: Conflict" + $verboseFile | Should -FileContentMatch "Retrying after interval of 2 seconds. Status code for previous attempt: TooManyRequests" } It "Invoke-RestMethod can retry with POST" { diff --git a/test/tools/WebListener/Controllers/RetryController.cs b/test/tools/WebListener/Controllers/RetryController.cs index 9a617bb7314..bdb70ff0f12 100644 --- a/test/tools/WebListener/Controllers/RetryController.cs +++ b/test/tools/WebListener/Controllers/RetryController.cs @@ -26,7 +26,7 @@ public JsonResult Retry(string sessionId, int failureCode, int failureCount, int { retryInfo ??= new Dictionary>(); - if (failureCode == 409 && retryAfter > 0) + if (failureCode == 429 && retryAfter > 0) { Response.Headers.Append("Retry-After", $"{retryAfter}"); }