diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs
index 13a2aa4ee40..b82d47952da 100644
--- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs
+++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs
@@ -75,6 +75,12 @@ public int MaximumFollowRelLink
[Alias("RHV")]
public string ResponseHeadersVariable { get; set; }
+ ///
+ /// Gets or sets the variable name to use for storing the status code from the response.
+ ///
+ [Parameter]
+ public string StatusCodeVariable { get; set; }
+
#endregion Parameters
#region Helper Methods
@@ -454,6 +460,12 @@ internal override void ProcessResponse(HttpResponseMessage response)
StreamHelper.SaveStreamToFile(responseStream, QualifiedOutFile, this);
}
+ if (!string.IsNullOrEmpty(StatusCodeVariable))
+ {
+ PSVariableIntrinsics vi = SessionState.PSVariable;
+ vi.Set(StatusCodeVariable, (int)response.StatusCode);
+ }
+
if (!string.IsNullOrEmpty(ResponseHeadersVariable))
{
PSVariableIntrinsics vi = SessionState.PSVariable;
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 6cdb5ecfbe6..d2d4417ab30 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
@@ -381,6 +381,12 @@ public virtual string CustomMethod
[Parameter]
public virtual SwitchParameter Resume { get; set; }
+ ///
+ /// Gets or sets whether to skip checking HTTP status for error codes.
+ ///
+ [Parameter]
+ public virtual SwitchParameter SkipHttpErrorCheck { get; set; }
+
#endregion
#endregion Virtual Properties
@@ -690,6 +696,11 @@ internal bool ShouldWriteToPipeline
get { return (!ShouldSaveToOutFile || PassThru); }
}
+ internal bool ShouldCheckHttpStatus
+ {
+ get { return !SkipHttpErrorCheck; }
+ }
+
///
/// Determines whether writing to a file should Resume and append rather than overwrite.
///
@@ -1242,7 +1253,7 @@ internal virtual void FillRequestStream(HttpRequestMessage request)
// Add the content headers
if (request.Content == null)
- {
+ {
request.Content = new StringContent(string.Empty);
request.Content.Headers.Clear();
}
@@ -1513,7 +1524,7 @@ protected override void ProcessRecord()
OutFile = null;
}
- if (!_isSuccess)
+ if (ShouldCheckHttpStatus && !_isSuccess)
{
string message = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure,
(int)response.StatusCode, response.ReasonPhrase);
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1
index b6d77ad4eff..d4ab2ff5009 100644
--- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1
+++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1
@@ -370,6 +370,13 @@ $redirectTests = @(
Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
BeforeAll {
$WebListener = Start-WebListener
+ $NotFoundQuery = @{
+ statuscode = 404
+ responsephrase = 'Not Found'
+ contenttype = 'text/plain'
+ body = 'oops'
+ headers = "{}"
+ }
}
# Validate the output of Invoke-WebRequest
@@ -780,6 +787,23 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
$result.Output.RelationLink["next"] | Should -BeExactly "${baseUri}?maxlinks=3&linknumber=2&type=${type}"
}
+ It "Verify Invoke-WebRequest supresses terminating errors with -SkipHttpErrorCheck" {
+ $uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery
+ $command = "Invoke-WebRequest -SkipHttpErrorCheck -Uri '$uri'"
+ $result = ExecuteWebCommand -Command $command
+ $result.output.StatusCode | Should -Be 404
+ $result.output.Content | Should -BeExactly "oops"
+ $result.error | Should -BeNullOrEmpty
+ }
+
+ It "Verify Invoke-WebRequest terminates without -SkipHttpErrorCheck" {
+ $uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery
+ $command = "Invoke-WebRequest -Uri '$uri'"
+ $result = ExecuteWebCommand -Command $command
+ $result.output | Should -BeNullOrEmpty
+ $result.error | Should -Not -BeNullOrEmpty
+ }
+
Context "Redirect" {
It "Validates Invoke-WebRequest with -PreserveAuthorizationOnRedirect preserves the authorization header on redirect: " -TestCases $redirectTests {
param($redirectType, $redirectedMethod)
@@ -1930,6 +1954,14 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
BeforeAll {
$WebListener = Start-WebListener
+
+ $NotFoundQuery = @{
+ statuscode = 404
+ responsephrase = 'Not Found'
+ contenttype = 'application/json'
+ body = '{"message": "oops"}'
+ headers = "{}"
+ }
}
#User-Agent changes on different platforms, so tests should only be run if on the correct platform
@@ -2259,6 +2291,64 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
1..3 | ForEach-Object { $result.Output[$_ - 1].linknumber | Should -BeExactly $_ }
}
+ It "Verify Invoke-RestMethod supresses terminating errors with -SkipHttpErrorCheck" {
+ $uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery
+ $command = "Invoke-RestMethod -SkipHttpErrorCheck -Uri '$uri'"
+ $result = ExecuteWebCommand -Command $command
+ $result.output.message | Should -BeExactly "oops"
+ $result.output.error | Should -BeNullOrEmpty
+ }
+
+ It "Verify Invoke-RestMethod terminates without -SkipHttpErrorCheck" {
+ $uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery
+ $command = "Invoke-RestMethod -Uri '$uri'"
+ $result = ExecuteWebCommand -Command $command
+ $result.output | Should -BeNullOrEmpty
+ $result.error | Should -Not -BeNullOrEmpty
+ }
+
+ It "Verify Invoke-RestMethod assigns 200 status code with -StatusCodeVariable" {
+ $query = @{
+ statuscode = 200
+ responsephrase = 'OK'
+ contenttype = 'application/json'
+ body = '{"message": "works"}'
+ headers = "{}"
+ }
+
+ $uri = Get-WebListenerUrl -Test 'Response' -Query $query
+ Invoke-RestMethod -StatusCodeVariable code -Uri "$uri"
+ $code | Should -Be 200
+ }
+
+ It "Verify Invoke-RestMethod assigns 404 status code with -StatusCodeVariable" {
+ $query = @{
+ statuscode = 404
+ responsephrase = 'Not Found'
+ contenttype = 'application/json'
+ body = '{"message": "oops"}'
+ headers = "{}"
+ }
+
+ $uri = Get-WebListenerUrl -Test 'Response' -Query $query
+ Invoke-RestMethod -SkipHttpErrorCheck -StatusCodeVariable code -Uri "$uri"
+ $code | Should -Be 404
+ }
+
+ It "Verify Invoke-RestMethod assigns 500 status code with -StatusCodeVariable" {
+ $query = @{
+ statuscode = 500
+ responsephrase = 'Internal Server Error'
+ contenttype = 'application/json'
+ body = '{"message": "oops"}'
+ headers = "{}"
+ }
+
+ $uri = Get-WebListenerUrl -Test 'Response' -Query $query
+ Invoke-RestMethod -SkipHttpErrorCheck -StatusCodeVariable code -Uri "$uri"
+ $code | Should -Be 500
+ }
+
#region Redirect tests
It "Validates Invoke-RestMethod with -PreserveAuthorizationOnRedirect preserves the authorization header on redirect: " -TestCases $redirectTests {
@@ -3387,4 +3477,3 @@ Describe "Web cmdlets tests using the cmdlet's aliases" -Tags "CI", "RequireAdmi
$result.Hello | Should -Be "world"
}
}
-