From 0d8be7b3857b88e376b6e4870c9da5246f2c4abf Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 23 Feb 2017 17:12:25 -0800 Subject: [PATCH 1/8] added http response to new HttpResponseException to provide similar experience to Windows PowerShell added tests for invoke-webrequest and invoke-restmethod for http error cases --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 50 +++++++++++++++++++ .../resources/WebCmdletStrings.resx | 3 ++ .../WebCmdlets.Tests.ps1 | 10 ++++ 3 files changed, 63 insertions(+) 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..d841565bf39 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 @@ -19,6 +19,50 @@ namespace Microsoft.PowerShell.Commands { + /// + /// Exception class for webcmdlets to enable returning HTTP error response + /// + public class HttpResponseException : Exception + { + private HttpResponseMessage _response; + private HttpStatusCode _status; + private HttpResponseHeaders _headers; + + /// + /// Constructor for HttpResponseException + /// + /// Message for the exception + public HttpResponseException (string message) : base(message) + {} + + /// + /// HTTP error response + /// + public HttpResponseMessage Response + { + get { return _response; } + set { _response = value; } + } + + /// + /// HTTP error status code + /// + public HttpStatusCode Status + { + get { return _status; } + set { _status = value; } + } + + /// + /// HTTP error headers + /// + public HttpResponseHeaders Headers + { + get { return _headers; } + set { _headers = value; } + } + } + /// /// Base class for Invoke-RestMethod and Invoke-WebRequest commands. /// @@ -355,6 +399,12 @@ protected override void ProcessRecord() response.Content.Headers.ContentLength, contentType); WriteVerbose(respVerboseMsg); + string message = String.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, + response.StatusCode.ToString(), response.ReasonPhrase); + HttpResponseException httpEx = new HttpResponseException(message); + httpEx.Response = response; + ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); + er.ErrorDetails = new ErrorDetails(message); ProcessResponse(response); UpdateSession(response); diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx index 368e34ad7be..b7256271e95 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} + + Response status code does not indicate success: {0} ({1}). + \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 11529315a69..920b472a075 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -399,6 +399,11 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error | Should BeNullOrEmpty } + $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException + $result.Error.Exception.Response.StatusCode | Should Be 418 + $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" + $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." + $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" } Describe "Invoke-RestMethod tests" -Tags "Feature" { @@ -642,6 +647,11 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error | Should BeNullOrEmpty } + $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException + $result.Error.Exception.Response.StatusCode | Should Be 418 + $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" + $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." + $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" } Describe "Validate Invoke-WebRequest and Invoke-RestMethod -InFile" -Tags "Feature" { From 6fe216af237295886bfa3a962378861ca621af21 Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Fri, 24 Feb 2017 10:46:56 -0800 Subject: [PATCH 2/8] fixed bad merge --- .../WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 6 +++++- .../WebCmdlets.Tests.ps1 | 13 +++++++++++++ 2 files changed, 18 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 d841565bf39..594cffb69d2 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 @@ -391,7 +391,6 @@ protected override void ProcessRecord() WriteVerbose(reqVerboseMsg); HttpResponseMessage response = GetResponse(client, request); - response.EnsureSuccessStatusCode(); string contentType = ContentHelper.GetContentType(response); string respVerboseMsg = string.Format(CultureInfo.CurrentCulture, @@ -399,12 +398,17 @@ protected override void ProcessRecord() response.Content.Headers.ContentLength, contentType); WriteVerbose(respVerboseMsg); + + if (!response.IsSuccessStatusCode) + { string message = String.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, response.StatusCode.ToString(), response.ReasonPhrase); HttpResponseException httpEx = new HttpResponseException(message); httpEx.Response = response; ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); er.ErrorDetails = new ErrorDetails(message); + ThrowTerminatingError(er); + } ProcessResponse(response); UpdateSession(response); diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 920b472a075..ad95a3e7f18 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -399,11 +399,18 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error | Should BeNullOrEmpty } + + It "Validate Invoke-WebRequest returns HTTP errors in exception" { + + $command = "Invoke-WebRequest -Uri http://httpstat.us/418" + $result = ExecuteWebCommand -command $command + $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException $result.Error.Exception.Response.StatusCode | Should Be 418 $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" + } } Describe "Invoke-RestMethod tests" -Tags "Feature" { @@ -647,11 +654,17 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error | Should BeNullOrEmpty } + + It "Validate Invoke-RestMethod returns HTTP errors in exception" { + + $command = "Invoke-RestMethod -Uri http://httpstat.us/418" + $result = ExecuteWebCommand -command $command $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException $result.Error.Exception.Response.StatusCode | Should Be 418 $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" + } } Describe "Validate Invoke-WebRequest and Invoke-RestMethod -InFile" -Tags "Feature" { From 192018798b93ca57adafd4c34c8209f249428c0f Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 23 Feb 2017 17:12:25 -0800 Subject: [PATCH 3/8] added http response to new HttpResponseException to provide similar experience to Windows PowerShell added tests for invoke-webrequest and invoke-restmethod for http error cases fixed bad merge --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 56 ++++++++++++++++++- .../resources/WebCmdletStrings.resx | 3 + .../WebCmdlets.Tests.ps1 | 23 ++++++++ 3 files changed, 81 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..594cffb69d2 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 @@ -19,6 +19,50 @@ namespace Microsoft.PowerShell.Commands { + /// + /// Exception class for webcmdlets to enable returning HTTP error response + /// + public class HttpResponseException : Exception + { + private HttpResponseMessage _response; + private HttpStatusCode _status; + private HttpResponseHeaders _headers; + + /// + /// Constructor for HttpResponseException + /// + /// Message for the exception + public HttpResponseException (string message) : base(message) + {} + + /// + /// HTTP error response + /// + public HttpResponseMessage Response + { + get { return _response; } + set { _response = value; } + } + + /// + /// HTTP error status code + /// + public HttpStatusCode Status + { + get { return _status; } + set { _status = value; } + } + + /// + /// HTTP error headers + /// + public HttpResponseHeaders Headers + { + get { return _headers; } + set { _headers = value; } + } + } + /// /// Base class for Invoke-RestMethod and Invoke-WebRequest commands. /// @@ -347,7 +391,6 @@ protected override void ProcessRecord() WriteVerbose(reqVerboseMsg); HttpResponseMessage response = GetResponse(client, request); - response.EnsureSuccessStatusCode(); string contentType = ContentHelper.GetContentType(response); string respVerboseMsg = string.Format(CultureInfo.CurrentCulture, @@ -355,6 +398,17 @@ protected override void ProcessRecord() response.Content.Headers.ContentLength, contentType); WriteVerbose(respVerboseMsg); + + if (!response.IsSuccessStatusCode) + { + string message = String.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, + response.StatusCode.ToString(), response.ReasonPhrase); + HttpResponseException httpEx = new HttpResponseException(message); + httpEx.Response = response; + ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); + er.ErrorDetails = new ErrorDetails(message); + ThrowTerminatingError(er); + } ProcessResponse(response); UpdateSession(response); diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/WebCmdletStrings.resx index 368e34ad7be..b7256271e95 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} + + Response status code does not indicate success: {0} ({1}). + \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 11529315a69..ad95a3e7f18 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -399,6 +399,18 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error | Should BeNullOrEmpty } + + It "Validate Invoke-WebRequest returns HTTP errors in exception" { + + $command = "Invoke-WebRequest -Uri http://httpstat.us/418" + $result = ExecuteWebCommand -command $command + + $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException + $result.Error.Exception.Response.StatusCode | Should Be 418 + $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" + $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." + $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" + } } Describe "Invoke-RestMethod tests" -Tags "Feature" { @@ -642,6 +654,17 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error | Should BeNullOrEmpty } + + It "Validate Invoke-RestMethod returns HTTP errors in exception" { + + $command = "Invoke-RestMethod -Uri http://httpstat.us/418" + $result = ExecuteWebCommand -command $command + $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException + $result.Error.Exception.Response.StatusCode | Should Be 418 + $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" + $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." + $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" + } } Describe "Validate Invoke-WebRequest and Invoke-RestMethod -InFile" -Tags "Feature" { From 8483c7ca3945c54f078ab0f48d50279d5341b8e7 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Fri, 24 Feb 2017 15:10:54 -0800 Subject: [PATCH 4/8] sealed HttpResponseException class, used auto-accessors, removed unused Headers and Status members, added response to constuctor based on feedback --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 37 ++++--------------- 1 file changed, 7 insertions(+), 30 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 594cffb69d2..02f991b9655 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 @@ -22,45 +22,23 @@ namespace Microsoft.PowerShell.Commands /// /// Exception class for webcmdlets to enable returning HTTP error response /// - public class HttpResponseException : Exception + public sealed class HttpResponseException : Exception { - private HttpResponseMessage _response; - private HttpStatusCode _status; - private HttpResponseHeaders _headers; - /// /// Constructor for HttpResponseException /// /// Message for the exception - public HttpResponseException (string message) : base(message) - {} - - /// - /// HTTP error response - /// - public HttpResponseMessage Response + /// Response from the HTTP server + public HttpResponseException (string message, HttpResponseMessage response) : base(message) { - get { return _response; } - set { _response = value; } + Response = response; } /// - /// HTTP error status code + /// HTTP error response /// - public HttpStatusCode Status - { - get { return _status; } - set { _status = value; } - } + public HttpResponseMessage Response { get; set; } - /// - /// HTTP error headers - /// - public HttpResponseHeaders Headers - { - get { return _headers; } - set { _headers = value; } - } } /// @@ -403,8 +381,7 @@ protected override void ProcessRecord() { string message = String.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, response.StatusCode.ToString(), response.ReasonPhrase); - HttpResponseException httpEx = new HttpResponseException(message); - httpEx.Response = response; + HttpResponseException httpEx = new HttpResponseException(message, response); ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); er.ErrorDetails = new ErrorDetails(message); ThrowTerminatingError(er); From eaaaa7fab81d9fdfab9625346fadcb0abe1382bf Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Fri, 24 Feb 2017 16:32:07 -0800 Subject: [PATCH 5/8] derived HttpResponseException from HttpRequestException so other catches continue to work added response stripping html tags to ErrorDetails added test to verify response is in ErrorDetails --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 14 ++++++++++---- .../WebCmdlets.Tests.ps1 | 7 +++++-- 2 files changed, 15 insertions(+), 6 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 73b9667fff7..44b89d0333e 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 @@ -22,7 +22,7 @@ namespace Microsoft.PowerShell.Commands /// /// Exception class for webcmdlets to enable returning HTTP error response /// - public sealed class HttpResponseException : Exception + public sealed class HttpResponseException : HttpRequestException { /// /// Constructor for HttpResponseException @@ -37,7 +37,7 @@ public HttpResponseException (string message, HttpResponseMessage response) : ba /// /// HTTP error response /// - public HttpResponseMessage Response { get; set; } + public HttpResponseMessage Response { get; private set; } } /// @@ -379,10 +379,16 @@ protected override void ProcessRecord() if (!response.IsSuccessStatusCode) { string message = String.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, - response.StatusCode.ToString(), response.ReasonPhrase); + Convert.ToInt32(response.StatusCode).ToString(), response.ReasonPhrase); HttpResponseException httpEx = new HttpResponseException(message, response); ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); - er.ErrorDetails = new ErrorDetails(message); + string detailMsg = ""; + using (StreamReader reader = new StreamReader(StreamHelper.GetResponseStream(response))) + { + // remove HTML tags making it easier to read + detailMsg = System.Text.RegularExpressions.Regex.Replace(reader.ReadToEnd(), "<[^>]*>",""); + } + er.ErrorDetails = new ErrorDetails(detailMsg); ThrowTerminatingError(er); } ProcessResponse(response); diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index ad95a3e7f18..ea76fda69a5 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -402,9 +402,10 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { It "Validate Invoke-WebRequest returns HTTP errors in exception" { - $command = "Invoke-WebRequest -Uri http://httpstat.us/418" + $command = "Invoke-WebRequest -Uri http://httpbin.org/status/418" $result = ExecuteWebCommand -command $command + $result.Error.ErrorDetails.Message | Should Match "\-=\[ teapot \]" $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException $result.Error.Exception.Response.StatusCode | Should Be 418 $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" @@ -657,8 +658,10 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { It "Validate Invoke-RestMethod returns HTTP errors in exception" { - $command = "Invoke-RestMethod -Uri http://httpstat.us/418" + $command = "Invoke-RestMethod -Uri http://httpbin.org/status/418" $result = ExecuteWebCommand -command $command + + $result.Error.ErrorDetails.Message | Should Match "\-=\[ teapot \]" $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException $result.Error.Exception.Response.StatusCode | Should Be 418 $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" From 4a8e6938df64ff000796befe3a6f9f67c74a8b91 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Fri, 24 Feb 2017 17:40:21 -0800 Subject: [PATCH 6/8] added try..catch around reading response stream and checking if detailMsg is empty changed error message test to be localization friendly by just matching the part returned from server --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 20 ++++++++++++++----- .../WebCmdlets.Tests.ps1 | 4 ++-- 2 files changed, 17 insertions(+), 7 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 44b89d0333e..bd0694fd6ca 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 @@ -379,16 +379,26 @@ protected override void ProcessRecord() if (!response.IsSuccessStatusCode) { string message = String.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, - Convert.ToInt32(response.StatusCode).ToString(), response.ReasonPhrase); + (int)response.StatusCode, response.ReasonPhrase); HttpResponseException httpEx = new HttpResponseException(message, response); ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); string detailMsg = ""; - using (StreamReader reader = new StreamReader(StreamHelper.GetResponseStream(response))) + try { - // remove HTML tags making it easier to read - detailMsg = System.Text.RegularExpressions.Regex.Replace(reader.ReadToEnd(), "<[^>]*>",""); + using (StreamReader reader = new StreamReader(StreamHelper.GetResponseStream(response))) + { + // remove HTML tags making it easier to read + detailMsg = System.Text.RegularExpressions.Regex.Replace(reader.ReadToEnd(), "<[^>]*>",""); + } + } + catch (Exception) + { + // catch all + } + if (!String.IsNullOrEmpty(detailMsg)) + { + er.ErrorDetails = new ErrorDetails(detailMsg); } - er.ErrorDetails = new ErrorDetails(detailMsg); ThrowTerminatingError(er); } ProcessResponse(response); diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index ea76fda69a5..66d618ddc61 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -409,7 +409,7 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException $result.Error.Exception.Response.StatusCode | Should Be 418 $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" - $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." + $result.Error.Exception.Message | Should Match ": 418 \(I'm a teapot\)\." $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" } } @@ -665,7 +665,7 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException $result.Error.Exception.Response.StatusCode | Should Be 418 $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" - $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." + $result.Error.Exception.Message | Should Match ": 418 \(I'm a teapot\)\." $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" } } From 4a420dbd48065b60bdb8cc062a16e080f933434c Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Fri, 24 Feb 2017 17:40:21 -0800 Subject: [PATCH 7/8] added try..catch..finally around reading response stream and checking if detailMsg is empty changed error message test to be localization friendly by just matching the part returned from server --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 18 +++++++++++++++--- .../WebCmdlets.Tests.ps1 | 4 ++-- 2 files changed, 17 insertions(+), 5 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 44b89d0333e..41b3293216f 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 @@ -379,16 +379,28 @@ protected override void ProcessRecord() if (!response.IsSuccessStatusCode) { string message = String.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, - Convert.ToInt32(response.StatusCode).ToString(), response.ReasonPhrase); + (int)response.StatusCode, response.ReasonPhrase); HttpResponseException httpEx = new HttpResponseException(message, response); ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); string detailMsg = ""; - using (StreamReader reader = new StreamReader(StreamHelper.GetResponseStream(response))) + StreamReader reader = new StreamReader(StreamHelper.GetResponseStream(response)); + try { // remove HTML tags making it easier to read detailMsg = System.Text.RegularExpressions.Regex.Replace(reader.ReadToEnd(), "<[^>]*>",""); } - er.ErrorDetails = new ErrorDetails(detailMsg); + catch (Exception) + { + // catch all + } + finally + { + reader.Dispose(); + } + if (!String.IsNullOrEmpty(detailMsg)) + { + er.ErrorDetails = new ErrorDetails(detailMsg); + } ThrowTerminatingError(er); } ProcessResponse(response); diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index ea76fda69a5..66d618ddc61 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -409,7 +409,7 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException $result.Error.Exception.Response.StatusCode | Should Be 418 $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" - $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." + $result.Error.Exception.Message | Should Match ": 418 \(I'm a teapot\)\." $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" } } @@ -665,7 +665,7 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException $result.Error.Exception.Response.StatusCode | Should Be 418 $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" - $result.Error.Exception.Message | Should Be "Response status code does not indicate success: 418 (I'm a teapot)." + $result.Error.Exception.Message | Should Match ": 418 \(I'm a teapot\)\." $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" } } From 650839bb8e41fff5a0854a75bf14cdeaafc82f18 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Fri, 24 Feb 2017 21:52:25 -0800 Subject: [PATCH 8/8] Add null check before disposing `reader` --- .../WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 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 8ab67d4144c..ca38c1ed3e6 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 @@ -396,7 +396,10 @@ protected override void ProcessRecord() } finally { - reader.Dispose(); + if (reader != null) + { + reader.Dispose(); + } } if (!String.IsNullOrEmpty(detailMsg)) { @@ -404,6 +407,7 @@ protected override void ProcessRecord() } ThrowTerminatingError(er); } + ProcessResponse(response); UpdateSession(response); @@ -591,4 +595,4 @@ internal long SetRequestContent(HttpRequestMessage request, IDictionary content) #endregion Helper Methods } } -#endif \ No newline at end of file +#endif