Skip to content

Commit 5b07fe2

Browse files
authored
Add BeforeTransport policy position (Azure#23055)
1 parent d99919d commit 5b07fe2

File tree

9 files changed

+115
-23
lines changed

9 files changed

+115
-23
lines changed

sdk/core/Azure.Core/api/Azure.Core.net461.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ public enum HttpPipelinePosition
322322
{
323323
PerCall = 0,
324324
PerRetry = 1,
325+
BeforeTransport = 2,
325326
}
326327
public abstract partial class Request : System.IDisposable
327328
{

sdk/core/Azure.Core/api/Azure.Core.net5.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ public enum HttpPipelinePosition
322322
{
323323
PerCall = 0,
324324
PerRetry = 1,
325+
BeforeTransport = 2,
325326
}
326327
public abstract partial class Request : System.IDisposable
327328
{

sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ public enum HttpPipelinePosition
322322
{
323323
PerCall = 0,
324324
PerRetry = 1,
325+
BeforeTransport = 2,
325326
}
326327
public abstract partial class Request : System.IDisposable
327328
{

sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ public enum HttpPipelinePosition
322322
{
323323
PerCall = 0,
324324
PerRetry = 1,
325+
BeforeTransport = 2,
325326
}
326327
public abstract partial class Request : System.IDisposable
327328
{

sdk/core/Azure.Core/src/ClientOptions.cs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,16 @@ internal ClientOptions(ClientOptions? clientOptions)
4343
Diagnostics = new DiagnosticsOptions(clientOptions.Diagnostics);
4444

4545
_transport = clientOptions.Transport;
46-
PerCallPolicies = new List<HttpPipelinePolicy>(clientOptions.PerCallPolicies);
47-
PerRetryPolicies = new List<HttpPipelinePolicy>(clientOptions.PerRetryPolicies);
46+
if (clientOptions.Policies != null)
47+
{
48+
Policies = new(clientOptions.Policies);
49+
}
4850
}
4951
else
5052
{
5153
// Intentionally leaving this null. The only consumer of this branch is
5254
// DefaultAzureCredential that would re-assign the value
5355
_transport = null!;
54-
PerCallPolicies = new List<HttpPipelinePolicy>();
55-
PerRetryPolicies = new List<HttpPipelinePolicy>();
5656
Diagnostics = new DiagnosticsOptions();
5757
Retry = new RetryOptions();
5858
}
@@ -86,22 +86,18 @@ public HttpPipelineTransport Transport
8686
/// <param name="position">The position of policy in the pipeline.</param>
8787
public void AddPolicy(HttpPipelinePolicy policy, HttpPipelinePosition position)
8888
{
89-
switch (position)
89+
if (position != HttpPipelinePosition.PerCall &&
90+
position != HttpPipelinePosition.PerRetry &&
91+
position != HttpPipelinePosition.BeforeTransport)
9092
{
91-
case HttpPipelinePosition.PerCall:
92-
PerCallPolicies.Add(policy);
93-
break;
94-
case HttpPipelinePosition.PerRetry:
95-
PerRetryPolicies.Add(policy);
96-
break;
97-
default:
98-
throw new ArgumentOutOfRangeException(nameof(position), position, null);
93+
throw new ArgumentOutOfRangeException(nameof(position), position, null);
9994
}
100-
}
10195

102-
internal IList<HttpPipelinePolicy> PerCallPolicies { get; }
96+
Policies ??= new();
97+
Policies.Add((position, policy));
98+
}
10399

104-
internal IList<HttpPipelinePolicy> PerRetryPolicies { get; }
100+
internal List<(HttpPipelinePosition Position, HttpPipelinePolicy Policy)>? Policies { get; private set; }
105101

106102
/// <inheritdoc />
107103
[EditorBrowsable(EditorBrowsableState.Never)]

sdk/core/Azure.Core/src/HttpPipelinePosition.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ public enum HttpPipelinePosition
1515
/// <summary>
1616
/// The policy would be invoked every time request is retried.
1717
/// </summary>
18-
PerRetry
18+
PerRetry,
19+
/// <summary>
20+
/// The policy would be invoked before the request is sent by the transport.
21+
/// </summary>
22+
BeforeTransport,
1923
}
2024
}

sdk/core/Azure.Core/src/Pipeline/HttpPipelineBuilder.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,32 @@ public static HttpPipeline Build(ClientOptions options, HttpPipelinePolicy[] per
4444
throw new ArgumentNullException(nameof(perRetryPolicies));
4545
}
4646

47-
var policies = new List<HttpPipelinePolicy>();
47+
var policies = new List<HttpPipelinePolicy>(8 +
48+
(options.Policies?.Count ?? 0) +
49+
perCallPolicies.Length +
50+
perRetryPolicies.Length);
51+
52+
void AddCustomerPolicies(HttpPipelinePosition position)
53+
{
54+
if (options.Policies != null)
55+
{
56+
foreach (var policy in options.Policies)
57+
{
58+
if (policy.Position == position)
59+
{
60+
policies.Add(policy.Policy);
61+
}
62+
}
63+
}
64+
}
4865

4966
bool isDistributedTracingEnabled = options.Diagnostics.IsDistributedTracingEnabled;
5067

5168
policies.Add(ReadClientRequestIdPolicy.Shared);
5269

5370
policies.AddRange(perCallPolicies);
5471

55-
policies.AddRange(options.PerCallPolicies);
72+
AddCustomerPolicies(HttpPipelinePosition.PerCall);
5673

5774
policies.Add(ClientRequestIdPolicy.Shared);
5875

@@ -69,7 +86,7 @@ public static HttpPipeline Build(ClientOptions options, HttpPipelinePolicy[] per
6986

7087
policies.AddRange(perRetryPolicies);
7188

72-
policies.AddRange(options.PerRetryPolicies);
89+
AddCustomerPolicies(HttpPipelinePosition.PerRetry);
7390

7491
if (diagnostics.IsLoggingEnabled)
7592
{
@@ -83,7 +100,9 @@ public static HttpPipeline Build(ClientOptions options, HttpPipelinePolicy[] per
83100

84101
policies.Add(new RequestActivityPolicy(isDistributedTracingEnabled, ClientDiagnostics.GetResourceProviderNamespace(options.GetType().Assembly)));
85102

86-
policies.RemoveAll(policy => policy == null);
103+
AddCustomerPolicies(HttpPipelinePosition.BeforeTransport);
104+
105+
policies.RemoveAll(static policy => policy == null);
87106

88107
return new HttpPipeline(options.Transport,
89108
policies.ToArray(),

sdk/core/Azure.Core/tests/ClientOptionsTests.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,21 @@ public static IEnumerable<object[]> ClientOptions()
160160
var policy = new PipelineSamples.StopwatchPolicy();
161161
o.AddPolicy(policy, HttpPipelinePosition.PerCall);
162162
return policy;
163-
}, o => o.PerCallPolicies.LastOrDefault());
163+
}, o => o.Policies?.LastOrDefault(p=>p.Position == HttpPipelinePosition.PerCall).Policy);
164164

165165
yield return M(o =>
166166
{
167167
var policy = new PipelineSamples.StopwatchPolicy();
168168
o.AddPolicy(policy, HttpPipelinePosition.PerRetry);
169169
return policy;
170-
}, o => o.PerRetryPolicies.LastOrDefault());
170+
}, o => o.Policies?.LastOrDefault(p=>p.Position == HttpPipelinePosition.PerRetry).Policy);
171+
172+
yield return M(o =>
173+
{
174+
var policy = new PipelineSamples.StopwatchPolicy();
175+
o.AddPolicy(policy, HttpPipelinePosition.BeforeTransport);
176+
return policy;
177+
}, o => o.Policies?.LastOrDefault(p=>p.Position == HttpPipelinePosition.BeforeTransport).Policy);
171178

172179
yield return M(o => o.Retry.Delay = TimeSpan.FromDays(5), o => o.Retry.Delay);
173180
yield return M(o => o.Retry.Mode = RetryMode.Fixed, o => o.Retry.Mode);

sdk/core/Azure.Core/tests/HttpPipelineBuilderTest.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class HttpPipelineBuilderTest : PolicyTestBase
1919
[Theory]
2020
[TestCase(HttpPipelinePosition.PerCall, 1)]
2121
[TestCase(HttpPipelinePosition.PerRetry, 2)]
22+
[TestCase(HttpPipelinePosition.BeforeTransport, 2)]
2223
public async Task CanAddCustomPolicy(HttpPipelinePosition position, int expectedCount)
2324
{
2425
var policy = new CounterPolicy();
@@ -40,6 +41,52 @@ public async Task CanAddCustomPolicy(HttpPipelinePosition position, int expected
4041
Assert.AreEqual(expectedCount, policy.ExecutionCount);
4142
}
4243

44+
[Test]
45+
public async Task CustomPolicyOrdering()
46+
{
47+
bool perCallRan = false;
48+
bool perRetryRan = false;
49+
bool beforeTransportRan = false;
50+
51+
var transport = new MockTransport(new MockResponse(200));
52+
var options = new TestOptions();
53+
54+
options.AddPolicy(new CallbackPolicy(m =>
55+
{
56+
perCallRan = true;
57+
Assert.False(perRetryRan);
58+
Assert.False(beforeTransportRan);
59+
}), HttpPipelinePosition.PerCall);
60+
61+
options.AddPolicy(new CallbackPolicy(m =>
62+
{
63+
perRetryRan = true;
64+
Assert.True(perCallRan);
65+
Assert.False(beforeTransportRan);
66+
}), HttpPipelinePosition.PerRetry);
67+
68+
options.AddPolicy(new CallbackPolicy(m =>
69+
{
70+
beforeTransportRan = true;
71+
Assert.True(perRetryRan);
72+
Assert.True(perCallRan);
73+
}), HttpPipelinePosition.BeforeTransport);
74+
75+
options.Transport = transport;
76+
77+
HttpPipeline pipeline = HttpPipelineBuilder.Build(options);
78+
79+
using Request request = transport.CreateRequest();
80+
request.Method = RequestMethod.Get;
81+
request.Uri.Reset(new Uri("http://example.com"));
82+
83+
await pipeline.SendRequestAsync(request, CancellationToken.None);
84+
85+
Assert.True(perRetryRan);
86+
Assert.True(perCallRan);
87+
Assert.True(beforeTransportRan);
88+
}
89+
4390
[Test]
4491
public async Task UsesAssemblyNameAndInformationalVersionForTelemetryPolicySettings()
4592
{
@@ -155,5 +202,20 @@ public override void OnSendingRequest(HttpMessage message)
155202

156203
public int ExecutionCount { get; set; }
157204
}
205+
206+
private class CallbackPolicy : HttpPipelineSynchronousPolicy
207+
{
208+
private readonly Action<HttpMessage> _message;
209+
210+
public CallbackPolicy(Action<HttpMessage> message)
211+
{
212+
_message = message;
213+
}
214+
215+
public override void OnSendingRequest(HttpMessage message)
216+
{
217+
_message(message);
218+
}
219+
}
158220
}
159221
}

0 commit comments

Comments
 (0)