diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs index 2797f92cc59..8bc9ad0e36e 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs @@ -16,6 +16,7 @@ using System.Security.Cryptography; using System.Threading; using System.Xml; +using Microsoft.PowerShell.CoreClr.Stubs; namespace Microsoft.PowerShell.Commands { @@ -347,7 +348,10 @@ protected override void ProcessRecord() WriteVerbose(reqVerboseMsg); HttpResponseMessage response = GetResponse(client, request); - response.EnsureSuccessStatusCode(); + if (!response.IsSuccessStatusCode) + { + ThrowNotSuccessStatusCodeError(request, response); + } string contentType = ContentHelper.GetContentType(response); string respVerboseMsg = string.Format(CultureInfo.CurrentCulture, @@ -408,6 +412,34 @@ protected override void StopProcessing() #region Helper Methods + private void ThrowNotSuccessStatusCodeError(HttpRequestMessage request, HttpResponseMessage response) + { + var detailMsg = ""; + var reader = new StreamReader(StreamHelper.GetResponseStream(response)); + try + { + detailMsg = reader.ReadToEnd(); + } + catch (IOException) + { + } + catch (ArgumentException) + { + } + finally + { + reader.Dispose(); + } + + var msg = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.NotSuccessStatusCode, (int) response.StatusCode, response.ReasonPhrase); + ErrorRecord er = new ErrorRecord(new WebException(msg) { Response = response }, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); + if (!String.IsNullOrEmpty(detailMsg)) + { + er.ErrorDetails = new ErrorDetails(detailMsg); + } + ThrowTerminatingError(er); + } + /// /// Sets the ContentLength property of the request and writes the specified content to the request's RequestStream. /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx index 368e34ad7be..c09782e061b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx +++ b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx @@ -210,4 +210,7 @@ Conversion from JSON failed with error: {0} + + The remote server returned an error: ({0}) {1}. + \ No newline at end of file diff --git a/src/System.Management.Automation/CoreCLR/CorePsStub.cs b/src/System.Management.Automation/CoreCLR/CorePsStub.cs index 662356ccf40..e45da35dc08 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsStub.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsStub.cs @@ -11,6 +11,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.Win32; using System.Management.Automation.Remoting; +using System.Net.Http; #pragma warning disable 1591, 1572, 1571, 1573, 1587, 1570, 0067 @@ -473,6 +474,23 @@ public sealed class AppDomainUnloadedException : Exception { } + /// + /// Stub for WebException + /// + public sealed class WebException : Exception + { + /// + /// Creates a new instance of the WebException + /// + /// + public WebException(string message) : base(message) { } + + /// + /// Gets the error message returned from the remote host. + /// + public HttpResponseMessage Response { get; set; } + } + #endregion Exception_Related #region SafeHandle_Related diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 11529315a69..67208e1b8d1 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -399,6 +399,20 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error | Should BeNullOrEmpty } + + It "Invoke-WebRequest should read content if status is unsuccessful" { + + $command = "Invoke-WebRequest http://httpbin.org/status/418" + $result = ExecuteWebCommand -command $command + $result.Error.ErrorDetails.Message | Should Match "\-=\[ teapot \]" + } + + It "Invoke-WebRequest should return status code if status is unsuccessful" { + + $command = "Invoke-WebRequest http://httpbin.org/status/500" + $result = ExecuteWebCommand -command $command + $result.Error.Exception.Response.StatusCode | Should be 500 + } } Describe "Invoke-RestMethod tests" -Tags "Feature" {