Skip to content

Commit cd8f557

Browse files
Merge pull request #367 from microsoftgraph/middlewareoptions
Request Context With Middleware Options
2 parents 2e1b2ae + 17f6932 commit cd8f557

38 files changed

+1181
-112
lines changed

src/Microsoft.Graph.Core/CoreConstants.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
33
// ------------------------------------------------------------------------------
44

5+
using System;
6+
57
namespace Microsoft.Graph
68
{
79
/// <summary>
@@ -33,6 +35,12 @@ public static class Headers
3335

3436
/// Throw-site header
3537
public const string ThrowSiteHeaderName = "X-ThrowSite";
38+
39+
/// Client Request Id
40+
public const string ClientRequestId = "client-request-id";
41+
42+
/// Feature Flag
43+
public const string FeatureFlag = "FeatureFlag";
3644
}
3745

3846
/// <summary>
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
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+
5+
namespace Microsoft.Graph
6+
{
7+
using System;
8+
using System.Net.Http;
9+
10+
/// <summary>
11+
/// Extension methods for <see cref="BaseRequest"/>
12+
/// </summary>
13+
public static class BaseRequestExtensions
14+
{
15+
16+
/// <summary>
17+
/// Sets the default authentication provider to the default Authentication Middleware Handler for this request.
18+
/// This only works with the default authentication handler.
19+
/// If you use a custom authentication handler, you have to handle it's retreival in your implementation.
20+
/// </summary>
21+
/// <typeparam name="T"></typeparam>
22+
/// <param name="baseRequest">The <see cref="BaseRequest"/> for the request.</param>
23+
/// <returns></returns>
24+
internal static T WithDefaultAuthProvider<T>(this T baseRequest) where T : IBaseRequest
25+
{
26+
string authOptionKey = typeof(AuthenticationHandlerOption).ToString();
27+
if (baseRequest.MiddlewareOptions.ContainsKey(authOptionKey))
28+
{
29+
(baseRequest.MiddlewareOptions[authOptionKey] as AuthenticationHandlerOption).AuthenticationProvider = baseRequest.Client.AuthenticationProvider;
30+
}
31+
else
32+
{
33+
baseRequest.MiddlewareOptions.Add(authOptionKey, new AuthenticationHandlerOption { AuthenticationProvider = baseRequest.Client.AuthenticationProvider });
34+
}
35+
return baseRequest;
36+
}
37+
38+
/// <summary>
39+
/// Sets the PerRequestAuthProvider delegate handler to the default Authentication Middleware Handler to authenticate a single request.
40+
/// The PerRequestAuthProvider delegate handler must be set to the GraphServiceClient instance before using this extension method otherwise, it defaults to the default authentication provider.
41+
/// This only works with the default authentication handler.
42+
/// If you use a custom authentication handler, you have to handle it's retreival in your implementation.
43+
/// </summary>
44+
/// <typeparam name="T"></typeparam>
45+
/// <param name="baseRequest">The <see cref="BaseRequest"/> for the request.</param>
46+
/// <returns></returns>
47+
public static T WithPerRequestAuthProvider<T>(this T baseRequest) where T : IBaseRequest
48+
{
49+
if (baseRequest.Client.PerRequestAuthProvider != null)
50+
{
51+
string authOptionKey = typeof(AuthenticationHandlerOption).ToString();
52+
if (baseRequest.MiddlewareOptions.ContainsKey(authOptionKey))
53+
{
54+
(baseRequest.MiddlewareOptions[authOptionKey] as AuthenticationHandlerOption).AuthenticationProvider = baseRequest.Client.PerRequestAuthProvider();
55+
}
56+
else
57+
{
58+
baseRequest.MiddlewareOptions.Add(authOptionKey, new AuthenticationHandlerOption { AuthenticationProvider = baseRequest.Client.PerRequestAuthProvider() });
59+
}
60+
}
61+
return baseRequest;
62+
}
63+
64+
/// <summary>
65+
/// Sets a ShouldRetry <see cref="Func{HttpResponseMessage, Boolean}"/> delegate to the default Retry Middleware Handler for this request.
66+
/// This only works with the default Retry Middleware Handler.
67+
/// If you use a custom Retry Middleware Handler, you have to handle it's retreival in your implementation.
68+
/// </summary>
69+
/// <typeparam name="T"></typeparam>
70+
/// <param name="baseRequest">The <see cref="BaseRequest"/> for the request.</param>
71+
/// <param name="shouldRetry">A <see cref="Func{HttpResponseMessage, Boolean}"/> for the request.</param>
72+
/// <returns></returns>
73+
public static T WithShouldRetry<T>(this T baseRequest, Func<HttpResponseMessage, bool> shouldRetry) where T : IBaseRequest
74+
{
75+
string retryOptionKey = typeof(RetryHandlerOption).ToString();
76+
if (baseRequest.MiddlewareOptions.ContainsKey(retryOptionKey))
77+
{
78+
(baseRequest.MiddlewareOptions[retryOptionKey] as RetryHandlerOption).ShouldRetry = shouldRetry;
79+
}
80+
else
81+
{
82+
baseRequest.MiddlewareOptions.Add(retryOptionKey, new RetryHandlerOption { ShouldRetry = shouldRetry });
83+
}
84+
return baseRequest;
85+
}
86+
87+
/// <summary>
88+
/// Sets the maximum number of retries to the default Retry Middleware Handler for this request.
89+
/// This only works with the default Retry Middleware Handler.
90+
/// If you use a custom Retry Middleware Handler, you have to handle it's retreival in your implementation.
91+
/// </summary>
92+
/// <typeparam name="T"></typeparam>
93+
/// <param name="baseRequest">The <see cref="BaseRequest"/> for the request.</param>
94+
/// <param name="maxRetry">The maxRetry for the request.</param>
95+
/// <returns></returns>
96+
public static T WithMaxRetry<T>(this T baseRequest, int maxRetry) where T : IBaseRequest
97+
{
98+
string retryOptionKey = typeof(RetryHandlerOption).ToString();
99+
if (baseRequest.MiddlewareOptions.ContainsKey(retryOptionKey))
100+
{
101+
(baseRequest.MiddlewareOptions[retryOptionKey] as RetryHandlerOption).MaxRetry = maxRetry;
102+
}
103+
else
104+
{
105+
baseRequest.MiddlewareOptions.Add(retryOptionKey, new RetryHandlerOption { MaxRetry = maxRetry });
106+
}
107+
return baseRequest;
108+
}
109+
110+
/// <summary>
111+
/// Sets the maximum number of redirects to the default Redirect Middleware Handler for this request.
112+
/// This only works with the default Redirect Middleware Handler.
113+
/// If you use a custom Redirect Middleware Handler, you have to handle it's retreival in your implementation.
114+
/// </summary>
115+
/// <typeparam name="T"></typeparam>
116+
/// <param name="baseRequest">The <see cref="BaseRequest"/> for the request.</param>
117+
/// <param name="maxRedirects">Maximum number of redirects allowed for the request</param>
118+
/// <returns></returns>
119+
public static T WithMaxRedirects<T>(this T baseRequest, int maxRedirects) where T : IBaseRequest
120+
{
121+
string redirectOptionKey = typeof(RedirectHandlerOption).ToString();
122+
if (baseRequest.MiddlewareOptions.ContainsKey(redirectOptionKey))
123+
{
124+
(baseRequest.MiddlewareOptions[redirectOptionKey] as RedirectHandlerOption).MaxRedirects = maxRedirects;
125+
}
126+
else
127+
{
128+
baseRequest.MiddlewareOptions.Add(redirectOptionKey, new RedirectHandlerOption { MaxRedirects = maxRedirects });
129+
}
130+
return baseRequest;
131+
}
132+
}
133+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
5+
namespace Microsoft.Graph
6+
{
7+
using System.Net.Http;
8+
9+
internal static class HttpClientExtensions
10+
{
11+
internal static void SetFeatureFlags(this HttpClient httpClient, FeatureFlag featureFlag)
12+
{
13+
httpClient.DefaultRequestHeaders.Add(CoreConstants.Headers.FeatureFlag, featureFlag.ToString());
14+
}
15+
}
16+
}

src/Microsoft.Graph.Core/Extensions/RequestExtensions.cs renamed to src/Microsoft.Graph.Core/Extensions/HttpRequestMessageExtensions.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44

55
namespace Microsoft.Graph
66
{
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Linq;
710
using System.Net.Http;
811
using System.Threading.Tasks;
912

1013
/// <summary>
1114
/// Contains extension methods for <see cref="HttpRequestMessage"/>
1215
/// </summary>
13-
internal static class RequestExtensions
16+
public static class HttpRequestMessageExtensions
1417
{
1518
/// <summary>
1619
/// Checks the HTTP request's content to determine if it's buffered or streamed content.
@@ -29,6 +32,23 @@ internal static bool IsBuffered(this HttpRequestMessage httpRequestMessage)
2932
return true;
3033
}
3134

35+
/// <summary>
36+
/// Get's feature request header value from the incoming <see cref="HttpRequestMessage"/>
37+
/// </summary>
38+
/// <param name="httpRequestMessage">The <see cref="HttpRequestMessage"/> object</param>
39+
/// <returns></returns>
40+
internal static FeatureFlag GetFeatureFlags(this HttpRequestMessage httpRequestMessage)
41+
{
42+
httpRequestMessage.Headers.TryGetValues(CoreConstants.Headers.FeatureFlag, out IEnumerable<string> flags);
43+
44+
if (!Enum.TryParse(flags?.FirstOrDefault(), out FeatureFlag featureFlag))
45+
{
46+
featureFlag = FeatureFlag.None;
47+
}
48+
49+
return featureFlag;
50+
}
51+
3252
/// <summary>
3353
/// Create a new HTTP request by copying previous HTTP request's headers and properties from response's request message.
3454
/// </summary>
@@ -59,5 +79,38 @@ internal static async Task<HttpRequestMessage> CloneAsync(this HttpRequestMessag
5979

6080
return newRequest;
6181
}
82+
83+
/// <summary>
84+
/// Gets a <see cref="GraphRequestContext"/> from <see cref="HttpRequestMessage"/>
85+
/// </summary>
86+
/// <param name="httpRequestMessage">The <see cref="HttpRequestMessage"/> representation of the request.</param>
87+
/// <returns></returns>
88+
public static GraphRequestContext GetRequestContext(this HttpRequestMessage httpRequestMessage)
89+
{
90+
GraphRequestContext requestContext = new GraphRequestContext();
91+
if (httpRequestMessage.Properties.TryGetValue(typeof(GraphRequestContext).ToString(), out var requestContextObject))
92+
{
93+
requestContext = (GraphRequestContext)requestContextObject;
94+
}
95+
return requestContext;
96+
}
97+
98+
/// <summary>
99+
/// Gets a <see cref="IMiddlewareOption"/> from <see cref="HttpRequestMessage"/>
100+
/// </summary>
101+
/// <typeparam name="T"></typeparam>
102+
/// <param name="httpRequestMessage">The <see cref="HttpRequestMessage"/> representation of the request.</param>
103+
/// <returns>A middleware option</returns>
104+
public static T GetMiddlewareOption<T>(this HttpRequestMessage httpRequestMessage) where T : IMiddlewareOption
105+
{
106+
IMiddlewareOption option = null;
107+
GraphRequestContext requestContext = httpRequestMessage.GetRequestContext();
108+
if (requestContext.MiddlewareOptions != null)
109+
{
110+
requestContext.MiddlewareOptions.TryGetValue(typeof(T).ToString(), out option);
111+
}
112+
return (T)option;
113+
}
114+
62115
}
63116
}

src/Microsoft.Graph.Core/Requests/BaseClient.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Microsoft.Graph
66
{
7-
using System.Threading.Tasks;
7+
using System;
88

99
/// <summary>
1010
/// A default <see cref="IBaseClient"/> implementation.
@@ -25,9 +25,15 @@ public BaseClient(
2525
IHttpProvider httpProvider = null)
2626
{
2727
this.BaseUrl = baseUrl;
28-
this.HttpProvider = httpProvider ?? new HttpProvider(authenticationProvider, new Serializer());
28+
this.AuthenticationProvider = authenticationProvider;
29+
this.HttpProvider = httpProvider ?? new HttpProvider(new Serializer());
2930
}
3031

32+
/// <summary>
33+
/// Gets the <see cref="IAuthenticationProvider"/> for authenticating requests.
34+
/// </summary>
35+
public IAuthenticationProvider AuthenticationProvider { get; set; }
36+
3137
/// <summary>
3238
/// Gets or sets the base URL for requests of the client.
3339
/// </summary>
@@ -54,5 +60,10 @@ public string BaseUrl
5460
/// Gets the <see cref="IHttpProvider"/> for sending HTTP requests.
5561
/// </summary>
5662
public IHttpProvider HttpProvider { get; private set; }
63+
64+
/// <summary>
65+
/// Gets or Sets the <see cref="IAuthenticationProvider"/> for authenticating a single HTTP requests.
66+
/// </summary>
67+
public Func<IAuthenticationProvider> PerRequestAuthProvider { get; set; }
5768
}
5869
}

0 commit comments

Comments
 (0)