Skip to content

Commit

Permalink
Merge pull request #1816 from tyrielv/nested-401
Browse files Browse the repository at this point in the history
Handle nested failures in HttpRequestException
  • Loading branch information
dscho authored Oct 24, 2024
2 parents f892a51 + 15d25e5 commit 17d346d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 9 deletions.
13 changes: 13 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
# especially
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot#enabling-dependabot-version-updates-for-actions

version: 2
updates:
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
18 changes: 9 additions & 9 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,25 @@ jobs:
run: src\scripts\CreateBuildArtifacts.bat ${{ matrix.configuration }} artifacts

- name: Upload functional tests drop
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: FunctionalTests_${{ matrix.configuration }}
path: artifacts\GVFS.FunctionalTests

- name: Upload FastFetch drop
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: FastFetch_${{ matrix.configuration }}
path: artifacts\FastFetch

- name: Upload installers
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: Installers_${{ matrix.configuration }}
path: artifacts\GVFS.Installers

- name: Upload NuGet packages
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: NuGetPackages_${{ matrix.configuration }}
path: artifacts\NuGetPackages
Expand All @@ -76,13 +76,13 @@ jobs:

steps:
- name: Download installers
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
name: Installers_${{ matrix.configuration }}
path: install

- name: Download functional tests drop
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
name: FunctionalTests_${{ matrix.configuration }}
path: ft
Expand All @@ -101,7 +101,7 @@ jobs:

- name: Upload installation logs
if: always()
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: InstallationLogs_${{ matrix.configuration }}
path: install\logs
Expand All @@ -115,14 +115,14 @@ jobs:
- name: Upload functional test results
if: always()
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: FunctionalTests_Results_${{ matrix.configuration }}
path: TestResult.xml

- name: Upload Git trace2 output
if: always()
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: GitTrace2_${{ matrix.configuration }}
path: C:\temp\git-trace2.log
Expand Down
51 changes: 51 additions & 0 deletions GVFS/GVFS.Common/Http/HttpRequestor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ protected GitEndPointResponseData SendRequest(
{
response = this.client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).GetAwaiter().GetResult();
}
catch (HttpRequestException httpRequestException) when (TryGetResponseMessageFromHttpRequestException(httpRequestException, request, out response))
{
/* HttpClientHandler will automatically resubmit in certain circumstances, such as a 401 unauthorized response when UseDefaultCredentials
* is true but another credential was provided. This resubmit can throw (instead of returning a proper status code) in some case cases, such
* as when there is an exception loading the default credentials.
* If we can extract the original response message from the exception, we can continue and process the original failed status code. */
Tracer.RelatedWarning(responseMetadata, $"An exception occurred while resubmitting the request, but the original response is available.");
}
finally
{
responseWaitTime = requestStopwatch.Elapsed;
Expand Down Expand Up @@ -278,5 +286,48 @@ private static string GetSingleHeaderOrEmpty(HttpHeaders headers, string headerN

return string.Empty;
}

/// <summary>
/// This method is based on a private method System.Net.Http.HttpClientHandler.CreateResponseMessage
/// </summary>
private static bool TryGetResponseMessageFromHttpRequestException(HttpRequestException httpRequestException, HttpRequestMessage request, out HttpResponseMessage httpResponseMessage)
{
var webResponse = (httpRequestException?.InnerException as WebException)?.Response as HttpWebResponse;
if (webResponse == null)
{
httpResponseMessage = null;
return false;
}

httpResponseMessage = new HttpResponseMessage(webResponse.StatusCode);
httpResponseMessage.ReasonPhrase = webResponse.StatusDescription;
httpResponseMessage.Version = webResponse.ProtocolVersion;
httpResponseMessage.RequestMessage = request;
httpResponseMessage.Content = new StreamContent(webResponse.GetResponseStream());
request.RequestUri = webResponse.ResponseUri;
WebHeaderCollection rawHeaders = webResponse.Headers;
HttpContentHeaders responseContentHeaders = httpResponseMessage.Content.Headers;
HttpResponseHeaders responseHeaders = httpResponseMessage.Headers;
if (webResponse.ContentLength >= 0)
{
responseContentHeaders.ContentLength = webResponse.ContentLength;
}

for (int i = 0; i < rawHeaders.Count; i++)
{
string key = rawHeaders.GetKey(i);
if (string.Compare(key, "Content-Length", StringComparison.OrdinalIgnoreCase) != 0)
{
string[] values = rawHeaders.GetValues(i);
if (!responseHeaders.TryAddWithoutValidation(key, values))
{
bool flag = responseContentHeaders.TryAddWithoutValidation(key, values);
}
}
}

return true;

}
}
}

0 comments on commit 17d346d

Please sign in to comment.