Skip to content

Increase request timeout to match default retry attempts. #1018

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

Merged
merged 5 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ public interface IAuthContext
ContextScope ContextScope { get; set; }
X509Certificate2 Certificate { get; set; }
Version PSHostVersion { get; set; }
TimeSpan ClientTimeout { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// ------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
// ------------------------------------------------------------------------------
namespace Microsoft.Graph.Authentication.Test.Helpers
{
using System;
using System.Net.Http;
using Microsoft.Graph.PowerShell.Authentication;
using Microsoft.Graph.PowerShell.Authentication.Helpers;
using Xunit;

public class HttpHelpersTests
{
[Fact]
public void GetGraphHttpClientWithDefaultParametersShouldReturnHttpClientWithDefaultTimeout()
{
GraphSession.Initialize(() => new GraphSession());
GraphSession.Instance.AuthContext = new AuthContext
{
AuthType = AuthenticationType.UserProvidedAccessToken,
ContextScope = ContextScope.Process
};

HttpClient httpClient = HttpHelpers.GetGraphHttpClient();

Assert.Equal(GraphSession.Instance.AuthContext.ClientTimeout, TimeSpan.FromSeconds(Constants.ClientTimeout));
Assert.Equal(httpClient.Timeout, GraphSession.Instance.AuthContext.ClientTimeout);

// reset static instance.
GraphSession.Reset();
}

[Fact]
public void GetGraphHttpClientWithClientTimeoutParameterShouldReturnHttpClientWithSpecifiedTimeout()
{
GraphSession.Initialize(() => new GraphSession());
TimeSpan timeSpan = TimeSpan.FromSeconds(10);
var authContext = new AuthContext
{
AuthType = AuthenticationType.UserProvidedAccessToken,
ContextScope = ContextScope.Process
};
IAuthenticationProvider authProvider = AuthenticationHelpers.GetAuthProvider(authContext);

HttpClient httpClient = HttpHelpers.GetGraphHttpClient(authProvider, timeSpan);

Assert.Equal(authContext.ClientTimeout, TimeSpan.FromSeconds(Constants.ClientTimeout));
Assert.Equal(httpClient.Timeout, timeSpan);

// reset static instance.
GraphSession.Reset();
}

[Fact]
public void GetGraphHttpClientShouldReturnHttpClientWithCustomerProvidedTimeout()
{
GraphSession.Initialize(() => new GraphSession());
TimeSpan timeSpan = TimeSpan.FromSeconds(10);
GraphSession.Instance.AuthContext = new AuthContext
{
AuthType = AuthenticationType.UserProvidedAccessToken,
ContextScope = ContextScope.Process,
ClientTimeout = timeSpan
};

HttpClient httpClient = HttpHelpers.GetGraphHttpClient();

Assert.Equal(GraphSession.Instance.AuthContext.ClientTimeout, timeSpan);
Assert.Equal(httpClient.Timeout, timeSpan);

// reset static instance.
GraphSession.Reset();
}
}
}
10 changes: 9 additions & 1 deletion src/Authentication/Authentication/Cmdlets/ConnectMgGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ public class ConnectMgGraph : PSCmdlet, IModuleAssemblyInitializer, IModuleAssem
Mandatory = false, HelpMessage = "Use device code authentication instead of a browser control")]
[Alias("DeviceCode", "DeviceAuth", "Device")]
public SwitchParameter UseDeviceAuthentication { get; set; }

[Parameter(ParameterSetName = Constants.AppParameterSet)]
[Parameter(ParameterSetName = Constants.AccessTokenParameterSet)]
[Parameter(ParameterSetName = Constants.UserParameterSet,
Mandatory = false,
HelpMessage = "Sets the HTTP client timeout in seconds.")]
[ValidateNotNullOrEmpty]
public double ClientTimeout { get; set; }
/// <summary>
/// Wait for .NET debugger to attach
/// </summary>
Expand Down Expand Up @@ -178,6 +186,7 @@ private async Task ProcessRecordAsync()
using (NoSynchronizationContext)
{
IAuthContext authContext = new AuthContext { TenantId = TenantId, PSHostVersion = this.Host.Version };
if (MyInvocation.BoundParameters.ContainsKey(nameof(ClientTimeout))) { authContext.ClientTimeout = TimeSpan.FromSeconds(ClientTimeout); }
// Set selected environment to the session object.
GraphSession.Instance.Environment = environment;
switch (ParameterSetName)
Expand Down Expand Up @@ -233,7 +242,6 @@ private async Task ProcessRecordAsync()

try
{

GraphSession.Instance.AuthContext = await Authenticator.AuthenticateAsync(authContext, ForceRefresh,
_cancellationTokenSource.Token,
() => { WriteWarning(Resources.DeviceCodeFallback); });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ private IAuthenticationProvider GetAuthProvider()
private HttpClient GetHttpClient()
{
var provider = GetAuthProvider();
var client = HttpHelpers.GetGraphHttpClient(provider);
var client = HttpHelpers.GetGraphHttpClient(provider, GraphSession.Instance.AuthContext.ClientTimeout);
return client;
}

Expand Down Expand Up @@ -1159,15 +1159,13 @@ private async Task ProcessRecordAsync()
{
var errorRecord = new ErrorRecord(httpRequestException, ErrorCategory.ConnectionError.ToString(),
ErrorCategory.InvalidResult, null);
httpRequestException.Data.Add(ErrorCategory.ConnectionError.ToString(), errorRecord);
throw;
ThrowTerminatingError(errorRecord);
}
catch (Exception exception)
{
var errorRecord = new ErrorRecord(exception, ErrorCategory.NotSpecified.ToString(),
ErrorCategory.InvalidOperation, null);
exception.Data.Add(ErrorCategory.NotSpecified.ToString(), errorRecord);
throw;
ThrowTerminatingError(errorRecord);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Authentication/Authentication/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Microsoft.Graph.PowerShell.Authentication
using System.IO;
public static class Constants
{
public const double ClientTimeout = 300;
public const int MaxContentLength = 10240;
public const string SDKHeaderValue = "graph-powershell/{0}.{1}.{2}";
internal const string UserParameterSet = "UserParameterSet";
Expand Down
6 changes: 4 additions & 2 deletions src/Authentication/Authentication/Helpers/HttpHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Microsoft.Graph.PowerShell.Authentication.Helpers
using System.Security.Authentication;
using Microsoft.Graph.PowerShell.Authentication.Handlers;
using System.Management.Automation;
using System;

/// <summary>
/// A HTTP helper class.
Expand Down Expand Up @@ -66,7 +67,7 @@ public static HttpClient GetGraphHttpClient(IAuthContext authContext = null)
}

IAuthenticationProvider authProvider = AuthenticationHelpers.GetAuthProvider(authContext);
return GetGraphHttpClient(authProvider);
return GetGraphHttpClient(authProvider, authContext.ClientTimeout);
}

/// <summary>
Expand All @@ -75,7 +76,7 @@ public static HttpClient GetGraphHttpClient(IAuthContext authContext = null)
/// </summary>
/// <param name="authProvider">Custom AuthProvider</param>
/// <returns></returns>
public static HttpClient GetGraphHttpClient(IAuthenticationProvider authProvider)
public static HttpClient GetGraphHttpClient(IAuthenticationProvider authProvider, TimeSpan clientTimeout)
{
IList<DelegatingHandler> defaultHandlers = GraphClientFactory.CreateDefaultHandlers(authProvider);

Expand All @@ -85,6 +86,7 @@ public static HttpClient GetGraphHttpClient(IAuthenticationProvider authProvider
defaultHandlers.Insert(2, new ODataQueryOptionsHandler());

HttpClient httpClient = GraphClientFactory.Create(defaultHandlers);
httpClient.Timeout = clientTimeout;

// Prepend SDKVersion header
PrependSDKHeader(httpClient, CoreConstants.Headers.SdkVersionHeaderName, AuthModuleVersionHeaderValue);
Expand Down
1 change: 1 addition & 0 deletions src/Authentication/Authentication/Models/AuthContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class AuthContext: IAuthContext
public ContextScope ContextScope { get ; set ; }
public X509Certificate2 Certificate { get; set; }
public Version PSHostVersion { get; set; }
public TimeSpan ClientTimeout { get; set; } = TimeSpan.FromSeconds(Constants.ClientTimeout);

public AuthContext()
{
Expand Down