Skip to content
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

Handle nested failures in HttpRequestException #1816

Merged
merged 3 commits into from
Oct 24, 2024

Conversation

tyrielv
Copy link
Contributor

@tyrielv tyrielv commented Oct 23, 2024

HttpClientHandler will automatically resubmit an HTTP request that fails in certain circumstances. One such circumstance is when UseDefaultCredentials is set to true, alternative credentials were provided on the request, and the request failed with 401 Unauthorized, then it will resubmit using the default credentials. If an exception is thrown when getting the default credentials that exception is not handled, but is wrapped in HttpRequestExceptionand thrown by SendAsync instead of returning the original response with the failing status code. Source

When this happens in GVFS, the result is that GVFS does not recognize the failure as being authentication related, so it does not refresh the credential. Instead, it loops through all its retries, and eventually fails the request. This is typically visible to users as a file system exception (e.g. file not found) if the GVFS trigger was accessing a virtual file or other operation on an individual file, or various errors (including "this repository requires the GVFS protocol") for a git pull. The symptoms will continue for the user until they remount the GVFS enlistment, which forces GVFS to refresh its credential.

This pull request adds an exception handler for HttpRequestException to client.SendAsync, which attempts to find the original failed response embedded in the inner exception properties. If it does so, it logs a warning and continues processing using the original failed response, which will trigger the logic for handling the various possible status codes. If it can't extract the original failed response, then it will let the exception bubble up.

The v2 version of `upload-artifact`/`download-artifact` is no longer
supported and stopped working. Let's update to v4, which _does_ work.

Signed-off-by: Johannes Schindelin <[email protected]>
Every once in a while, the GitHub Actions we use (such as `checkout`,
`upload-artifact`, etc) require updates as the old versions stop
working.

Let's ask Dependabot to take care of this tedious task.

Signed-off-by: Johannes Schindelin <[email protected]>
`HttpClientHandler` will automatically resubmit an HTTP request that
fails in certain circumstances. One such circumstance is when
`UseDefaultCredentials` is set to `true``, alternative credentials were
provided on the request, and the request failed with "401 Unauthorized",
then it will resubmit using the default credentials. If an exception is
thrown when getting the default credentials that exception is not
handled, but is wrapped in `HttpRequestExceptio`n and thrown by
`SendAsync` instead of returning the original response with the failing
status code. See the following code snippet from `HttpWebRequest`:
https://referencesource.microsoft.com/#System/net/System/Net/HttpWebRequest.cs,5535

When this happens in GVFS, the result is that GVFS does not recognize
the failure as being authentication related, so it does not refresh the
credential. Instead, it loops through all its retries, and eventually
fails the request. This is typically visible to users as a file system
exception (e.g. file not found) if the GVFS trigger was accessing a
virtual file or other operation on an individual file, or various errors
(including "this repository requires the GVFS protocol") for a `git
pull`. The symptoms will continue for the user until they remount the
GVFS enlistment, which forces GVFS to refresh its credential.

This commit adds an exception handler for `HttpRequestException`` to
`client.SendAsync`, which attempts to find the original failed response
embedded in the inner exception properties. If it does so, it logs a
warning and continues processing using the original failed response,
which will trigger the logic for handling the various possible status
codes. If it can't extract the original failed response, then it will
let the exception bubble up.

Signed-off-by: Tyrie Vella <[email protected]>
Signed-off-by: Johannes Schindelin <[email protected]>
Copy link
Member

@dscho dscho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

I opened #1817 to fix the build failures, rebased this commit and amended the commit message.

@dscho dscho merged commit 17d346d into microsoft:master Oct 24, 2024
5 checks passed
@dscho dscho mentioned this pull request Oct 24, 2024
@dscho dscho added this to the M195 milestone Oct 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants