From 91db5308f9c003d4edc5e04b1d5b552e39302ea8 Mon Sep 17 00:00:00 2001 From: 2xmax <2xmax@mail.ru> Date: Fri, 3 Feb 2017 01:59:06 +0300 Subject: [PATCH 1/5] error message and status code in the Invoke-WebRequest cmdlet [Fixes#2113] --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 15 ++++++++++++++- .../resources/WebCmdletStrings.resx | 3 +++ .../CoreCLR/CorePsStub.cs | 18 ++++++++++++++++++ .../WebCmdlets.Tests.ps1 | 14 ++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) 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..795a5c31b5b 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 @@ -347,7 +347,20 @@ protected override void ProcessRecord() WriteVerbose(reqVerboseMsg); HttpResponseMessage response = GetResponse(client, request); - response.EnsureSuccessStatusCode(); + if (!response.IsSuccessStatusCode) + { + using(var reader = new StreamReader(StreamHelper.GetResponseStream(response))) + { + var detailMsg = reader.ReadToEnd(); + var msg = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.NotSuccessStatusCode, 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); + } + } string contentType = ContentHelper.GetContentType(response); string respVerboseMsg = string.Format(CultureInfo.CurrentCulture, diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx index 368e34ad7be..61301fa2833 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:d}) {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..c382a87fe08 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 + /// + /// + 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" { From 5eb8af49201542803d32650555e2f6ee7214d895 Mon Sep 17 00:00:00 2001 From: 2xmax <2xmax@mail.ru> Date: Fri, 3 Feb 2017 02:10:09 +0300 Subject: [PATCH 2/5] docs --- src/System.Management.Automation/CoreCLR/CorePsStub.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/CoreCLR/CorePsStub.cs b/src/System.Management.Automation/CoreCLR/CorePsStub.cs index c382a87fe08..e45da35dc08 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsStub.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsStub.cs @@ -480,7 +480,7 @@ public sealed class AppDomainUnloadedException : Exception public sealed class WebException : Exception { /// - /// Creates a new instance of the + /// Creates a new instance of the WebException /// /// public WebException(string message) : base(message) { } From 4e351917f0e10c7371b60c1ef996d7c33dafe68b Mon Sep 17 00:00:00 2001 From: 2xmax <2xmax@mail.ru> Date: Fri, 3 Feb 2017 02:31:20 +0300 Subject: [PATCH 3/5] fixed build --- .../utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 1 + 1 file changed, 1 insertion(+) 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 795a5c31b5b..a6f85a4db72 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 { From dabb348d71c98bf2e8181038d44f8eb186aa1808 Mon Sep 17 00:00:00 2001 From: 2xmax <2xmax@mail.ru> Date: Fri, 3 Feb 2017 19:47:22 +0300 Subject: [PATCH 4/5] moved error creation to a separate method --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) 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 a6f85a4db72..c3bc3696d5a 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 @@ -350,17 +350,7 @@ protected override void ProcessRecord() HttpResponseMessage response = GetResponse(client, request); if (!response.IsSuccessStatusCode) { - using(var reader = new StreamReader(StreamHelper.GetResponseStream(response))) - { - var detailMsg = reader.ReadToEnd(); - var msg = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.NotSuccessStatusCode, 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); - } + ThrowNotSuccessStatusCodeError(request, response); } string contentType = ContentHelper.GetContentType(response); @@ -422,6 +412,21 @@ protected override void StopProcessing() #region Helper Methods + private void ThrowNotSuccessStatusCodeError(HttpRequestMessage request, HttpResponseMessage response) + { + using(var reader = new StreamReader(StreamHelper.GetResponseStream(response))) + { + var detailMsg = reader.ReadToEnd(); + var msg = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.NotSuccessStatusCode, 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. /// From f37e8bbc8302b7fe8bc7f4736bdc6b3266f0d4c6 Mon Sep 17 00:00:00 2001 From: 2xmax <2xmax@mail.ru> Date: Wed, 8 Feb 2017 02:33:00 +0300 Subject: [PATCH 5/5] exception handling as full clr does; simpler string formatting logic --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 31 +++++++++++++------ .../resources/WebCmdletStrings.resx | 2 +- 2 files changed, 23 insertions(+), 10 deletions(-) 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 c3bc3696d5a..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 @@ -414,17 +414,30 @@ protected override void StopProcessing() private void ThrowNotSuccessStatusCodeError(HttpRequestMessage request, HttpResponseMessage response) { - using(var reader = new StreamReader(StreamHelper.GetResponseStream(response))) + var detailMsg = ""; + var reader = new StreamReader(StreamHelper.GetResponseStream(response)); + try { - var detailMsg = reader.ReadToEnd(); - var msg = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.NotSuccessStatusCode, 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); + 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); } /// diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx index 61301fa2833..c09782e061b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx +++ b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx @@ -211,6 +211,6 @@ Conversion from JSON failed with error: {0} - The remote server returned an error: ({0:d}) {1}. + The remote server returned an error: ({0}) {1}. \ No newline at end of file