Skip to content

Commit 2879b49

Browse files
peombwageorgend
andauthored
Increase request timeout to match default retry attempts. (#1018)
* Increase HTTP client timeout. * Add -ClientTimeout to Connect-MgGraph. Co-authored-by: George <[email protected]>
1 parent 78c3b62 commit 2879b49

File tree

7 files changed

+94
-8
lines changed

7 files changed

+94
-8
lines changed

src/Authentication/Authentication.Core/Interfaces/IAuthContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ public interface IAuthContext
4343
ContextScope ContextScope { get; set; }
4444
X509Certificate2 Certificate { get; set; }
4545
Version PSHostVersion { get; set; }
46+
TimeSpan ClientTimeout { get; set; }
4647
}
4748
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// ------------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
3+
// ------------------------------------------------------------------------------
4+
namespace Microsoft.Graph.Authentication.Test.Helpers
5+
{
6+
using System;
7+
using System.Net.Http;
8+
using Microsoft.Graph.PowerShell.Authentication;
9+
using Microsoft.Graph.PowerShell.Authentication.Helpers;
10+
using Xunit;
11+
12+
public class HttpHelpersTests
13+
{
14+
[Fact]
15+
public void GetGraphHttpClientWithDefaultParametersShouldReturnHttpClientWithDefaultTimeout()
16+
{
17+
GraphSession.Initialize(() => new GraphSession());
18+
GraphSession.Instance.AuthContext = new AuthContext
19+
{
20+
AuthType = AuthenticationType.UserProvidedAccessToken,
21+
ContextScope = ContextScope.Process
22+
};
23+
24+
HttpClient httpClient = HttpHelpers.GetGraphHttpClient();
25+
26+
Assert.Equal(GraphSession.Instance.AuthContext.ClientTimeout, TimeSpan.FromSeconds(Constants.ClientTimeout));
27+
Assert.Equal(httpClient.Timeout, GraphSession.Instance.AuthContext.ClientTimeout);
28+
29+
// reset static instance.
30+
GraphSession.Reset();
31+
}
32+
33+
[Fact]
34+
public void GetGraphHttpClientWithClientTimeoutParameterShouldReturnHttpClientWithSpecifiedTimeout()
35+
{
36+
GraphSession.Initialize(() => new GraphSession());
37+
TimeSpan timeSpan = TimeSpan.FromSeconds(10);
38+
var authContext = new AuthContext
39+
{
40+
AuthType = AuthenticationType.UserProvidedAccessToken,
41+
ContextScope = ContextScope.Process
42+
};
43+
IAuthenticationProvider authProvider = AuthenticationHelpers.GetAuthProvider(authContext);
44+
45+
HttpClient httpClient = HttpHelpers.GetGraphHttpClient(authProvider, timeSpan);
46+
47+
Assert.Equal(authContext.ClientTimeout, TimeSpan.FromSeconds(Constants.ClientTimeout));
48+
Assert.Equal(httpClient.Timeout, timeSpan);
49+
50+
// reset static instance.
51+
GraphSession.Reset();
52+
}
53+
54+
[Fact]
55+
public void GetGraphHttpClientShouldReturnHttpClientWithCustomerProvidedTimeout()
56+
{
57+
GraphSession.Initialize(() => new GraphSession());
58+
TimeSpan timeSpan = TimeSpan.FromSeconds(10);
59+
GraphSession.Instance.AuthContext = new AuthContext
60+
{
61+
AuthType = AuthenticationType.UserProvidedAccessToken,
62+
ContextScope = ContextScope.Process,
63+
ClientTimeout = timeSpan
64+
};
65+
66+
HttpClient httpClient = HttpHelpers.GetGraphHttpClient();
67+
68+
Assert.Equal(GraphSession.Instance.AuthContext.ClientTimeout, timeSpan);
69+
Assert.Equal(httpClient.Timeout, timeSpan);
70+
71+
// reset static instance.
72+
GraphSession.Reset();
73+
}
74+
}
75+
}

src/Authentication/Authentication/Cmdlets/ConnectMgGraph.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ public class ConnectMgGraph : PSCmdlet, IModuleAssemblyInitializer, IModuleAssem
101101
Mandatory = false, HelpMessage = "Use device code authentication instead of a browser control")]
102102
[Alias("DeviceCode", "DeviceAuth", "Device")]
103103
public SwitchParameter UseDeviceAuthentication { get; set; }
104+
105+
[Parameter(ParameterSetName = Constants.AppParameterSet)]
106+
[Parameter(ParameterSetName = Constants.AccessTokenParameterSet)]
107+
[Parameter(ParameterSetName = Constants.UserParameterSet,
108+
Mandatory = false,
109+
HelpMessage = "Sets the HTTP client timeout in seconds.")]
110+
[ValidateNotNullOrEmpty]
111+
public double ClientTimeout { get; set; }
104112
/// <summary>
105113
/// Wait for .NET debugger to attach
106114
/// </summary>
@@ -178,6 +186,7 @@ private async Task ProcessRecordAsync()
178186
using (NoSynchronizationContext)
179187
{
180188
IAuthContext authContext = new AuthContext { TenantId = TenantId, PSHostVersion = this.Host.Version };
189+
if (MyInvocation.BoundParameters.ContainsKey(nameof(ClientTimeout))) { authContext.ClientTimeout = TimeSpan.FromSeconds(ClientTimeout); }
181190
// Set selected environment to the session object.
182191
GraphSession.Instance.Environment = environment;
183192
switch (ParameterSetName)
@@ -233,7 +242,6 @@ private async Task ProcessRecordAsync()
233242

234243
try
235244
{
236-
237245
GraphSession.Instance.AuthContext = await Authenticator.AuthenticateAsync(authContext, ForceRefresh,
238246
_cancellationTokenSource.Token,
239247
() => { WriteWarning(Resources.DeviceCodeFallback); });

src/Authentication/Authentication/Cmdlets/InvokeMgGraphRequest.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ private IAuthenticationProvider GetAuthProvider()
568568
private HttpClient GetHttpClient()
569569
{
570570
var provider = GetAuthProvider();
571-
var client = HttpHelpers.GetGraphHttpClient(provider);
571+
var client = HttpHelpers.GetGraphHttpClient(provider, GraphSession.Instance.AuthContext.ClientTimeout);
572572
return client;
573573
}
574574

@@ -1159,15 +1159,13 @@ private async Task ProcessRecordAsync()
11591159
{
11601160
var errorRecord = new ErrorRecord(httpRequestException, ErrorCategory.ConnectionError.ToString(),
11611161
ErrorCategory.InvalidResult, null);
1162-
httpRequestException.Data.Add(ErrorCategory.ConnectionError.ToString(), errorRecord);
1163-
throw;
1162+
ThrowTerminatingError(errorRecord);
11641163
}
11651164
catch (Exception exception)
11661165
{
11671166
var errorRecord = new ErrorRecord(exception, ErrorCategory.NotSpecified.ToString(),
11681167
ErrorCategory.InvalidOperation, null);
1169-
exception.Data.Add(ErrorCategory.NotSpecified.ToString(), errorRecord);
1170-
throw;
1168+
ThrowTerminatingError(errorRecord);
11711169
}
11721170
}
11731171
}

src/Authentication/Authentication/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace Microsoft.Graph.PowerShell.Authentication
77
using System.IO;
88
public static class Constants
99
{
10+
public const double ClientTimeout = 300;
1011
public const int MaxContentLength = 10240;
1112
public const string SDKHeaderValue = "graph-powershell/{0}.{1}.{2}";
1213
internal const string UserParameterSet = "UserParameterSet";

src/Authentication/Authentication/Helpers/HttpHelpers.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Microsoft.Graph.PowerShell.Authentication.Helpers
1111
using System.Security.Authentication;
1212
using Microsoft.Graph.PowerShell.Authentication.Handlers;
1313
using System.Management.Automation;
14+
using System;
1415

1516
/// <summary>
1617
/// A HTTP helper class.
@@ -66,7 +67,7 @@ public static HttpClient GetGraphHttpClient(IAuthContext authContext = null)
6667
}
6768

6869
IAuthenticationProvider authProvider = AuthenticationHelpers.GetAuthProvider(authContext);
69-
return GetGraphHttpClient(authProvider);
70+
return GetGraphHttpClient(authProvider, authContext.ClientTimeout);
7071
}
7172

7273
/// <summary>
@@ -75,7 +76,7 @@ public static HttpClient GetGraphHttpClient(IAuthContext authContext = null)
7576
/// </summary>
7677
/// <param name="authProvider">Custom AuthProvider</param>
7778
/// <returns></returns>
78-
public static HttpClient GetGraphHttpClient(IAuthenticationProvider authProvider)
79+
public static HttpClient GetGraphHttpClient(IAuthenticationProvider authProvider, TimeSpan clientTimeout)
7980
{
8081
IList<DelegatingHandler> defaultHandlers = GraphClientFactory.CreateDefaultHandlers(authProvider);
8182

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

8788
HttpClient httpClient = GraphClientFactory.Create(defaultHandlers);
89+
httpClient.Timeout = clientTimeout;
8890

8991
// Prepend SDKVersion header
9092
PrependSDKHeader(httpClient, CoreConstants.Headers.SdkVersionHeaderName, AuthModuleVersionHeaderValue);

src/Authentication/Authentication/Models/AuthContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class AuthContext: IAuthContext
2121
public ContextScope ContextScope { get ; set ; }
2222
public X509Certificate2 Certificate { get; set; }
2323
public Version PSHostVersion { get; set; }
24+
public TimeSpan ClientTimeout { get; set; } = TimeSpan.FromSeconds(Constants.ClientTimeout);
2425

2526
public AuthContext()
2627
{

0 commit comments

Comments
 (0)