GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — return HTTP response for error status as part of exception by SteveL-MSFT · Pull Request #3201 · PowerShell/PowerShell Conversation
Member
Addresses #2193 When Invoke-WebRequest or Invoke-RestMethod receives a HTTS status error code, an exception is returned and the user can't get the HTTP response without additional work. This change makes it more consistent with Windows PowerShell in that a Response property which contains the HttpResponse is a member of the resulting Exception.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions…xperience to Windows PowerShell added tests for invoke-webrequest and invoke-restmethod for http error cases …xperience to Windows PowerShell added tests for invoke-webrequest and invoke-restmethod for http error cases fixed bad merge
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. Should this class be sealed? Or is there a reason to derive from it?
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
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. Agree, no reason to derive from it
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
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. It looks like this property is never set in the error handling code below. Does this just return the response.StatusCode?
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
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. Was originally adding the individual properties before I saw the example of Windows PowerShell just having a Response property. Didn't remove them. Will remove.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
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. Same for this property. Is this _response.Headers?
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
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. Will remove.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
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. I believe we normally use automatic implemented getter/setter property syntax: public HttpResponseMessage Response { get; set; }
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
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. Will fix
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
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. You could use this syntax here for creating the HttpResponseException: Or you could make the constructor take all property values and make the properties read only.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
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. Will change constructor
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
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. Should we test for Exception.Headers and Exception.Status too?
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
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. Those are getting removed
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions…ed Headers and Status members, added response to constuctor based on feedback
Member
Author
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
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. We should make the setter private { get; private set; }. Otherwise LGTM.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
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.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
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. Makes sense
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was an error while loading. Please reload this page.
|
Steve Lee (@SteveL-MSFT) We have another similar PR here #3089, please take a look at the comments in that PR to see any of them apply in this fix as well. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Max Maximov (@2xmax) (the author of #3089). would you mind take a look? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
will the new version of the cmdlet output the content if the code was unsuccessful? I could say in the context of my scope, that was a real issue and we even already rewrote our code to curl instead of powershell whereas the status code was not a case, afaik we were able to parse it using regex:)). UPD: sorry, I found it the response property. But now the problem is, the response now is not disposed properly as the FullClr impl does |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Max Maximov (@2xmax) you are right, this PR only covers partial of #3089. It doesn't capture the content from the response and put it in Steve Lee (@SteveL-MSFT), do you want to address it in this same PR or a different one? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| { | ||
| /// <summary> | ||
| /// Exception class for webcmdlets to enable returning HTTP error response | ||
| /// </summary> |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I suggest we make HttpResponseException derive from HttpRequestException, so that { Invoke-WebRequest <url> } catch [HttpRequestException] { } will continue to work after this change.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Agree
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| HttpResponseException httpEx = new HttpResponseException(message, response); | ||
| ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); | ||
| er.ErrorDetails = new ErrorDetails(message); | ||
| ThrowTerminatingError(er); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Will make the change
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| $result = ExecuteWebCommand -command $command | ||
| $result.Error | Should BeNullOrEmpty | ||
| } | ||
|
|
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
pls add a test with a response content
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
will do
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…hes continue to work added response stripping html tags to ErrorDetails added test to verify response is in ErrorDetails
|
Addressed feedback. This should also address #2113 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| 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))) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Exceptions may be thrown out in StreamHelper.GetResponseStream(response) or reader.ReadToEnd(). We should put the using block in a try/catch-all block, just like what we did in full ps.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
ok
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| if (!response.IsSuccessStatusCode) | ||
| { | ||
| string message = String.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure, | ||
| Convert.ToInt32(response.StatusCode).ToString(), response.ReasonPhrase); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Convert.ToInt32(response.StatusCode).ToString()
A minor comment: maybe just (int)response.StatusCode as in HttpResponseMessage.cs?
If we want to avoid boxing the int argument, then it should be ((int)response.StatusCode).ToString(), but maybe it's an overkill 😄
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with just the cast
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| // remove HTML tags making it easier to read | ||
| detailMsg = System.Text.RegularExpressions.Regex.Replace(reader.ReadToEnd(), "<[^>]*>",""); | ||
| } | ||
| er.ErrorDetails = new ErrorDetails(detailMsg); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
er.ErrorDetails should be set only if detailMsg is not an empty string..
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
ok
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| $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)." |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Minor comment: this might fail if we are going to run this test on a localized machine.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Dongbo Wang (@daxian-dbw) Is a match good enough for the part returned from the server?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
changed to Match
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think so, $result.Error.Exception.Message | Should BeLike * 418 (I'm a teapot) should be good, since they are returned from the Http service, not affected by PS localization.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| $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)." |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Same minor comment here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
changed to Match
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…lMsg is empty changed error message test to be localization friendly by just matching the part returned from server
| { | ||
| /// <summary> | ||
| /// Exception class for webcmdlets to enable returning HTTP error response | ||
| /// </summary> |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I suggest moving the class into a separate file
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I did a search of the existing source and it appears that in some cases Exceptions are declared in a separate file (like SessionStateExceptions.cs), but in many other cases, the Exception is declared where it's used (like parserutils.cs).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| HttpResponseException httpEx = new HttpResponseException(message, response); | ||
| ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); | ||
| string detailMsg = ""; | ||
| try |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I suggest using try-catch-finally to avoid nesting
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
ok
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Max Maximov (@2xmax) do you mean like this?
StreamReader reader = null;
try
{
reader = new StreamReader(StreamHelper.GetResponseStream(response))
....
}
catch { }
finally { if (reader != null) { reader.Dispose(); } }
Sorry, something went wrong.
There was an error while loading. Please reload this page.
… if detailMsg is empty changed error message test to be localization friendly by just matching the part returned from server
| HttpResponseException httpEx = new HttpResponseException(message, response); | ||
| ErrorRecord er = new ErrorRecord(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request); | ||
| string detailMsg = ""; | ||
| StreamReader reader = new StreamReader(StreamHelper.GetResponseStream(response)); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid you need to put new StreamReader(StreamHelper.GetResponseStream(response)); in the try block. Maybe like this:
string detailMsg = "";
StreamReader reader = null;
try
{
reader = new StreamReader(StreamHelper.GetResponseStream(response))
detailMsg = System.Text.RegularExpressions.Regex.Replace(reader.ReadToEnd(), "<[^>]*>","");
}
catch { }
finally { if (reader != null) { reader.Dispose(); } }
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
fixed
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| @@ -0,0 +1,610 @@ | |||
| #if CORECLR | |||
|
|
|||
| /********************************************************************++ | |||
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
And this file got committed by accident 😄
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
fixed
Sorry, something went wrong.
There was an error while loading. Please reload this page.
new commits were pushed.
moved allocation of StreamReader into try block
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.