Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3f6bf74
add test for AddPolicy
annelo-msft Nov 5, 2021
a92daef
Merge remote-tracking branch 'upstream/main' into core-reqopts-addpolicy
annelo-msft Nov 8, 2021
3343e31
share proposed refactoring to HttpPipelineExtensions
annelo-msft Nov 8, 2021
83388fa
ideas in the direction of implementation
annelo-msft Nov 9, 2021
f15d1e9
mark retry policy
annelo-msft Nov 9, 2021
c5128a6
revert mark retry policy
annelo-msft Nov 10, 2021
f378649
shifting API around
annelo-msft Nov 11, 2021
d4f88c8
experiment with using MemoryPool
annelo-msft Nov 11, 2021
b6cb9d5
use ArrayPool
annelo-msft Nov 11, 2021
0daab39
use ArrayPool
annelo-msft Nov 11, 2021
04b5d15
add tests
annelo-msft Nov 12, 2021
901d34c
update API
annelo-msft Nov 12, 2021
40046dd
throw if didn't use pipeline builder
annelo-msft Nov 12, 2021
e8f55df
Merge remote-tracking branch 'upstream/main' into core-reqopts-addpolicy
annelo-msft Nov 12, 2021
89962b6
pr feedback and merge follow-up
annelo-msft Nov 12, 2021
a698972
Merge remote-tracking branch 'upstream/main' into core-reqopts-addpolicy
annelo-msft Nov 12, 2021
faafa33
pr fb and merge follow-up
annelo-msft Nov 13, 2021
a11d08e
pr fb
annelo-msft Nov 16, 2021
fda1c48
Merge remote-tracking branch 'upstream/main' into core-reqopts-addpolicy
annelo-msft Nov 16, 2021
b442ee1
simplify request pipeline creation
annelo-msft Nov 16, 2021
18120d7
move AddPolicy tests to Core; pr fb
annelo-msft Nov 16, 2021
88d0b74
nit
annelo-msft Nov 16, 2021
acba415
pr fb
annelo-msft Nov 16, 2021
2c325a1
pr fb & fix build
annelo-msft Nov 16, 2021
cdaf0d4
pr fb
annelo-msft Nov 17, 2021
9409ca4
pr fb & build fix
annelo-msft Nov 17, 2021
a681bc1
pr fb
annelo-msft Nov 17, 2021
38b6880
pr fb
annelo-msft Nov 17, 2021
eaf6f28
pr fb & fix core ci
annelo-msft Nov 17, 2021
fa7c8e0
revert files used for testing
annelo-msft Nov 17, 2021
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 @@ -146,7 +146,7 @@ public virtual Response GetPet(string id, RequestContext context = null)
/// <param name="options"> The request options. </param>
private HttpMessage CreateGetPetRequest(string id, RequestContext context = null)
{
var message = Pipeline.CreateMessage();
var message = Pipeline.CreateMessage(context);
var request = message.Request;
request.Method = RequestMethod.Get;
var uri = new RawRequestUriBuilder();
Expand Down
164 changes: 164 additions & 0 deletions sdk/core/Azure.Core.Experimental/tests/LowLevelClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Core.Experimental.Tests;
Expand Down Expand Up @@ -211,6 +212,145 @@ public void ThrowOnErrorThrowsOnError()
});
}

[Test]
public async Task CanAddPerCallPolicy()
Comment thread
annelo-msft marked this conversation as resolved.
Outdated
{
var petResponse = new MockResponse(200);

Pet pet = new("snoopy", "beagle");
petResponse.SetContent(SerializationHelpers.Serialize(pet, SerializePet));

var mockTransport = new MockTransport(petResponse);
PetStoreClient client = CreateClient(mockTransport);

var context = new RequestContext();
context.AddPolicy(new AddHeaderPolicy("PerCallHeader", "Value"), HttpPipelinePosition.PerCall);

Response response = await client.GetPetAsync("snoopy", context);

Request request = mockTransport.Requests[0];
Assert.IsTrue(request.Headers.TryGetValues("PerCallHeader", out var values));
Assert.AreEqual(1, values.Count());
Assert.AreEqual("Value", values.ElementAt(0));
}

[Test]
public async Task CanAddPerRetryPolicy()
{
var retryResponse = new MockResponse(408); // Request Timeout
var petResponse = new MockResponse(200);

Pet pet = new("snoopy", "beagle");
petResponse.SetContent(SerializationHelpers.Serialize(pet, SerializePet));

// retry twice -- this will add the header three times.
var mockTransport = new MockTransport(retryResponse, retryResponse, petResponse);
PetStoreClient client = CreateClient(mockTransport);

var context = new RequestContext();
context.AddPolicy(new AddHeaderPolicy("PerRetryHeader", "Value"), HttpPipelinePosition.PerRetry);

Response response = await client.GetPetAsync("snoopy", context);

Request request = mockTransport.Requests[0];
Assert.IsTrue(request.Headers.TryGetValues("PerRetryHeader", out var values));
Assert.AreEqual(3, values.Count());
Assert.AreEqual("Value", values.ElementAt(0));
Assert.AreEqual("Value", values.ElementAt(1));
Assert.AreEqual("Value", values.ElementAt(2));
}

[Test]
public async Task CanAddBeforeTransportPolicy()
{
var retryResponse = new MockResponse(408); // Request Timeout
var petResponse = new MockResponse(200);

Pet pet = new("snoopy", "beagle");
petResponse.SetContent(SerializationHelpers.Serialize(pet, SerializePet));

// retry twice
var mockTransport = new MockTransport(retryResponse, retryResponse, petResponse);
PetStoreClient client = CreateClient(mockTransport);

var context = new RequestContext();
context.AddPolicy(new AddHeaderPolicy("BeforeTransportHeader", "Value"), HttpPipelinePosition.BeforeTransport);

Response response = await client.GetPetAsync("snoopy", context);

Request request = mockTransport.Requests[0];
Assert.IsTrue(request.Headers.TryGetValues("BeforeTransportHeader", out var values));
Assert.AreEqual(3, values.Count());
Assert.AreEqual("Value", values.ElementAt(0));
Assert.AreEqual("Value", values.ElementAt(1));
Assert.AreEqual("Value", values.ElementAt(2));
}

[Test]
public async Task CanAddPoliciesAllPositions()
Comment thread
annelo-msft marked this conversation as resolved.
Outdated
{
var retryResponse = new MockResponse(408); // Request Timeout
var petResponse = new MockResponse(200);

Pet pet = new("snoopy", "beagle");
petResponse.SetContent(SerializationHelpers.Serialize(pet, SerializePet));

// retry twice -- this will add the header three times.
var mockTransport = new MockTransport(retryResponse, retryResponse, petResponse);
PetStoreClient client = CreateClient(mockTransport);

var context = new RequestContext();
context.AddPolicy(new AddHeaderPolicy("PerCallHeader1", "PerCall1"), HttpPipelinePosition.PerCall);
context.AddPolicy(new AddHeaderPolicy("PerCallHeader2", "PerCall2"), HttpPipelinePosition.PerCall);
context.AddPolicy(new AddHeaderPolicy("PerRetryHeader", "PerRetry"), HttpPipelinePosition.PerRetry);
context.AddPolicy(new AddHeaderPolicy("BeforeTransportHeader", "BeforeTransport"), HttpPipelinePosition.BeforeTransport);

Response response = await client.GetPetAsync("snoopy", context);

Request request = mockTransport.Requests[0];

Assert.IsTrue(request.Headers.TryGetValues("PerCallHeader1", out var perCall1Values));
Assert.AreEqual(1, perCall1Values.Count());
Assert.AreEqual("PerCall1", perCall1Values.ElementAt(0));

Assert.IsTrue(request.Headers.TryGetValues("PerCallHeader2", out var perCall2Values));
Assert.AreEqual(1, perCall2Values.Count());
Assert.AreEqual("PerCall2", perCall2Values.ElementAt(0));

Assert.IsTrue(request.Headers.TryGetValues("PerRetryHeader", out var perRetryValues));
Assert.AreEqual("PerRetry", perRetryValues.ElementAt(0));
Assert.AreEqual("PerRetry", perRetryValues.ElementAt(1));
Assert.AreEqual("PerRetry", perRetryValues.ElementAt(2));

Assert.IsTrue(request.Headers.TryGetValues("BeforeTransportHeader", out var beforeTransportValues));
Assert.AreEqual("BeforeTransport", beforeTransportValues.ElementAt(0));
Assert.AreEqual("BeforeTransport", beforeTransportValues.ElementAt(1));
Assert.AreEqual("BeforeTransport", beforeTransportValues.ElementAt(2));
}

[Test]
public async Task ThrowsIfUsePipelineConstructor()
{
HttpPipeline pipeline = new HttpPipeline(new MockTransport());

var context = new RequestContext();
context.AddPolicy(new AddHeaderPolicy("PerCallHeader", "Value"), HttpPipelinePosition.PerCall);

var message = pipeline.CreateMessage(context);

bool throws = false;
try
{
await pipeline.SendAsync(message, context.CancellationToken);
}
catch (InvalidOperationException)
{
throws = true;
}

Assert.IsTrue(throws);
}

#region Helpers
private void SerializePet(ref Utf8JsonWriter writer, Pet pet)
{
Expand All @@ -224,6 +364,30 @@ private void SerializePet(ref Utf8JsonWriter writer, Pet pet)

writer.WriteEndObject();
}

public class AddHeaderPolicy : HttpPipelinePolicy
Comment thread
annelo-msft marked this conversation as resolved.
Outdated
{
private string _headerName;
private string _headerVaue;

public AddHeaderPolicy(string headerName, string headerValue) : base()
{
_headerName = headerName;
_headerVaue = headerValue;
}

public override void Process(HttpMessage message, ReadOnlyMemory<HttpPipelinePolicy> pipeline)
{
message.Request.Headers.Add(_headerName, _headerVaue);
ProcessNext(message, pipeline);
}

public override ValueTask ProcessAsync(HttpMessage message, ReadOnlyMemory<HttpPipelinePolicy> pipeline)
{
message.Request.Headers.Add(_headerName, _headerVaue);
return ProcessNextAsync(message, pipeline);
}
}
#endregion
}
}
2 changes: 2 additions & 0 deletions sdk/core/Azure.Core/api/Azure.Core.net461.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public partial class RequestContext
public RequestContext() { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } set { } }
public Azure.ErrorOptions ErrorOptions { get { throw null; } set { } }
public void AddPolicy(Azure.Core.Pipeline.HttpPipelinePolicy policy, Azure.Core.HttpPipelinePosition position) { }
public static implicit operator Azure.RequestContext (Azure.ErrorOptions options) { throw null; }
}
public partial class RequestFailedException : System.Exception, System.Runtime.Serialization.ISerializable
Expand Down Expand Up @@ -755,6 +756,7 @@ public HttpPipeline(Azure.Core.Pipeline.HttpPipelineTransport transport, Azure.C
public static System.IDisposable CreateClientRequestIdScope(string? clientRequestId) { throw null; }
public static System.IDisposable CreateHttpMessagePropertiesScope(System.Collections.Generic.IDictionary<string, object?> messageProperties) { throw null; }
public Azure.Core.HttpMessage CreateMessage() { throw null; }
public Azure.Core.HttpMessage CreateMessage(Azure.RequestContext context) { throw null; }
public Azure.Core.Request CreateRequest() { throw null; }
public void Send(Azure.Core.HttpMessage message, System.Threading.CancellationToken cancellationToken) { }
public System.Threading.Tasks.ValueTask SendAsync(Azure.Core.HttpMessage message, System.Threading.CancellationToken cancellationToken) { throw null; }
Expand Down
2 changes: 2 additions & 0 deletions sdk/core/Azure.Core/api/Azure.Core.net5.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public partial class RequestContext
public RequestContext() { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } set { } }
public Azure.ErrorOptions ErrorOptions { get { throw null; } set { } }
public void AddPolicy(Azure.Core.Pipeline.HttpPipelinePolicy policy, Azure.Core.HttpPipelinePosition position) { }
public static implicit operator Azure.RequestContext (Azure.ErrorOptions options) { throw null; }
}
public partial class RequestFailedException : System.Exception, System.Runtime.Serialization.ISerializable
Expand Down Expand Up @@ -755,6 +756,7 @@ public HttpPipeline(Azure.Core.Pipeline.HttpPipelineTransport transport, Azure.C
public static System.IDisposable CreateClientRequestIdScope(string? clientRequestId) { throw null; }
public static System.IDisposable CreateHttpMessagePropertiesScope(System.Collections.Generic.IDictionary<string, object?> messageProperties) { throw null; }
public Azure.Core.HttpMessage CreateMessage() { throw null; }
public Azure.Core.HttpMessage CreateMessage(Azure.RequestContext context) { throw null; }
public Azure.Core.Request CreateRequest() { throw null; }
public void Send(Azure.Core.HttpMessage message, System.Threading.CancellationToken cancellationToken) { }
public System.Threading.Tasks.ValueTask SendAsync(Azure.Core.HttpMessage message, System.Threading.CancellationToken cancellationToken) { throw null; }
Expand Down
2 changes: 2 additions & 0 deletions sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public partial class RequestContext
public RequestContext() { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } set { } }
public Azure.ErrorOptions ErrorOptions { get { throw null; } set { } }
public void AddPolicy(Azure.Core.Pipeline.HttpPipelinePolicy policy, Azure.Core.HttpPipelinePosition position) { }
public static implicit operator Azure.RequestContext (Azure.ErrorOptions options) { throw null; }
}
public partial class RequestFailedException : System.Exception, System.Runtime.Serialization.ISerializable
Expand Down Expand Up @@ -755,6 +756,7 @@ public HttpPipeline(Azure.Core.Pipeline.HttpPipelineTransport transport, Azure.C
public static System.IDisposable CreateClientRequestIdScope(string? clientRequestId) { throw null; }
public static System.IDisposable CreateHttpMessagePropertiesScope(System.Collections.Generic.IDictionary<string, object?> messageProperties) { throw null; }
public Azure.Core.HttpMessage CreateMessage() { throw null; }
public Azure.Core.HttpMessage CreateMessage(Azure.RequestContext context) { throw null; }
public Azure.Core.Request CreateRequest() { throw null; }
public void Send(Azure.Core.HttpMessage message, System.Threading.CancellationToken cancellationToken) { }
public System.Threading.Tasks.ValueTask SendAsync(Azure.Core.HttpMessage message, System.Threading.CancellationToken cancellationToken) { throw null; }
Expand Down
2 changes: 2 additions & 0 deletions sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public partial class RequestContext
public RequestContext() { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } set { } }
public Azure.ErrorOptions ErrorOptions { get { throw null; } set { } }
public void AddPolicy(Azure.Core.Pipeline.HttpPipelinePolicy policy, Azure.Core.HttpPipelinePosition position) { }
public static implicit operator Azure.RequestContext (Azure.ErrorOptions options) { throw null; }
}
public partial class RequestFailedException : System.Exception, System.Runtime.Serialization.ISerializable
Expand Down Expand Up @@ -755,6 +756,7 @@ public HttpPipeline(Azure.Core.Pipeline.HttpPipelineTransport transport, Azure.C
public static System.IDisposable CreateClientRequestIdScope(string? clientRequestId) { throw null; }
public static System.IDisposable CreateHttpMessagePropertiesScope(System.Collections.Generic.IDictionary<string, object?> messageProperties) { throw null; }
public Azure.Core.HttpMessage CreateMessage() { throw null; }
public Azure.Core.HttpMessage CreateMessage(Azure.RequestContext context) { throw null; }
public Azure.Core.Request CreateRequest() { throw null; }
public void Send(Azure.Core.HttpMessage message, System.Threading.CancellationToken cancellationToken) { }
public System.Threading.Tasks.ValueTask SendAsync(Azure.Core.HttpMessage message, System.Threading.CancellationToken cancellationToken) { throw null; }
Expand Down
2 changes: 2 additions & 0 deletions sdk/core/Azure.Core/src/HttpMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public Response Response
/// </summary>
public TimeSpan? NetworkTimeout { get; set; }

internal List<(HttpPipelinePosition Position, HttpPipelinePolicy Policy)>? Policies { get; set; }

/// <summary>
/// Gets a property that modifies the pipeline behavior. Please refer to individual policies documentation on what properties it supports.
/// </summary>
Expand Down
Loading