-
Notifications
You must be signed in to change notification settings - Fork 8.1k
error message and status code in the Invoke-WebRequest cmdlet [Fixes#… #3089
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
91db530
5eb8af4
4e35191
dabb348
f37e8bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In full PS, a simple regex replace is used to remove tags from the content. We probably should do the same. |
||
| } | ||
| 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); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It's great to get the detailed message for the error record to keep a consistent behavior. But I don't think we should use a stub type to mimic the exception in full PS.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @daxian-dbw Well, I agree that the Response property looks kind of weird here. However, it helps keep backward compatibility. For example, given an http request, I need to get the status code In the case of non-200 response, is there another straight way to get the status code in the FullClr implementation except for
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm thinking aloud here: how about we add the response object to "Exception.Data" for core PS? Users can get the status code by
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @TravisEz13 @lzybkr @vors can you please take a look and share your opinions?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are real cases where the response data is needed. Some sites send details of the error in the body, etc. I agree that putting the response under data is less discoverable. The exception message from the base exception should not be altered, though.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @daxian-dbw in both cases we considered we would have trade-offs. However, in the case of From another side, in the case of the Response field, oh yes, we would have that a little bit tricky exception logic in the CoreClr implementation, but all that logic would be encapsulated in that method and with tests we could get along with that. Plus, if we find a third solution later, we can refactor it whereas with that breaking change it could be far more complex. Does anybody have the third solution for this problem:))?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree One problem here is that |
||
| if (!String.IsNullOrEmpty(detailMsg)) | ||
| { | ||
| er.ErrorDetails = new ErrorDetails(detailMsg); | ||
| } | ||
| ThrowTerminatingError(er); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Sets the ContentLength property of the request and writes the specified content to the request's RequestStream. | ||
| /// </summary> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | |
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Stub for WebException | ||
| /// </summary> | ||
| public sealed class WebException : Exception | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think creating a sub type named |
||
| { | ||
| /// <summary> | ||
| /// Creates a new instance of the WebException | ||
| /// </summary> | ||
| /// <param name="message"></param> | ||
| public WebException(string message) : base(message) { } | ||
|
|
||
| /// <summary> | ||
| /// Gets the error message returned from the remote host. | ||
| /// </summary> | ||
| public HttpResponseMessage Response { get; set; } | ||
| } | ||
|
|
||
| #endregion Exception_Related | ||
|
|
||
| #region SafeHandle_Related | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could
response.Contentbe null and raiseNullReferenceExceptioninGetResponseStream? Maybe we should checkresponse.Content != null && response.Content.Headers.ContentLength > 0before getting its stream.And also, could
response.Content.ReadAsStreamAsyncraise any exception when the response is not in success status? Maybe the code dealing with stream should be put in a try/catch-all block, just like how it does in full PS.