Skip to content
Closed
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 @@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFrameworks>$(RequiredTargetFrameworks)</TargetFrameworks>
<IncludeGeneratorSharedCode>true</IncludeGeneratorSharedCode>
<DefineConstants>$(DefineConstants);EXPERIMENTAL</DefineConstants>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ public static implicit operator Pet(Response response)
return DeserializePet(JsonDocument.Parse(response.Content.ToMemory()));
}

// Cast from BinaryData to Pet
public static implicit operator Pet(BinaryData binaryData)
{
//// [X] TODO: Add in HLC error semantics
//// [X] TODO: Use response.IsError
//// [X] TODO: Use throw new ResponseFailedException(response);

//// TODO: When we move this functionality out of Experimental into Core, it will be replaced by
//// > if (response.IsError)
//if (response.IsError())
//{
// // TODO: When we move this functionality out of Experimental into Core, it will be replaced by
// // > throw new RequestFailedException(response);
// throw response.CreateRequestFailedException();
//}

return DeserializePet(JsonDocument.Parse(binaryData.ToMemory()));
}

private static Pet DeserializePet(JsonDocument document)
{
return new Pet(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
#nullable disable

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Core.Pipeline;

namespace Azure.Core.Experimental.Tests
Expand All @@ -16,7 +20,7 @@ public partial class PetStoreClient
public virtual HttpPipeline Pipeline { get; }
private readonly string[] AuthorizationScopes = { "https://example.azurepetshop.com/.default" };
private readonly TokenCredential _tokenCredential;
private Uri endpoint;
private Uri _endpoint;
private readonly string apiVersion;
private readonly ClientDiagnostics _clientDiagnostics;
private ResponseClassifier _classifier200;
Expand Down Expand Up @@ -60,7 +64,7 @@ public PetStoreClient(Uri endpoint, TokenCredential credential, PetStoreClientOp

// TODO: When we move the IsError functionality into Core, we'll move the addition of ResponsePropertiesPolicy to the pipeline into HttpPipelineBuilder.
Pipeline = HttpPipelineBuilder.Build(options, new HttpPipelinePolicy[] { new LowLevelCallbackPolicy() }, new HttpPipelinePolicy[] { authPolicy, new ResponsePropertiesPolicy(options) }, new ResponseClassifier());
this.endpoint = endpoint;
_endpoint = endpoint;
apiVersion = options.Version;
}

Expand Down Expand Up @@ -150,7 +154,7 @@ private HttpMessage CreateGetPetRequest(string id, RequestContext context = null
var request = message.Request;
request.Method = RequestMethod.Get;
var uri = new RawRequestUriBuilder();
uri.Reset(endpoint);
uri.Reset(_endpoint);
uri.AppendPath("/pets/", false);
uri.AppendPath(id, true);
request.Uri = uri;
Expand All @@ -159,17 +163,98 @@ private HttpMessage CreateGetPetRequest(string id, RequestContext context = null
return message;
}

private class ResponseClassifier200 : ResponseClassifier
#pragma warning disable AZC0002
public virtual AsyncPageable<BinaryData> GetPetsAsync(RequestContext context = null)
#pragma warning restore AZC0002
{
return PageableHelpers.CreateAsyncPageable(CreateEnumerableAsync, _clientDiagnostics, "PetStoreClient.GetPets");
async IAsyncEnumerable<Page<BinaryData>> CreateEnumerableAsync(string nextLink, int? pageSizeHint, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
do
{
var message = string.IsNullOrEmpty(nextLink)
? CreateGetPetsRequest()
: CreateGetPetsNextPageRequest(nextLink);
var page = await LowLevelPageableHelpers.ProcessMessageAsync(Pipeline, message, _clientDiagnostics, context, "value", "nextLink", cancellationToken).ConfigureAwait(false);
nextLink = page.ContinuationToken;
yield return page;
} while (!string.IsNullOrEmpty(nextLink));
}
}

#pragma warning disable AZC0002
public virtual Pageable<BinaryData> GetPets(RequestContext context = null)
#pragma warning restore AZC0002
{
return PageableHelpers.CreatePageable(CreateEnumerable, _clientDiagnostics, "PetStoreClient.GetPets");
IEnumerable<Page<BinaryData>> CreateEnumerable(string nextLink, int? pageSizeHint)
{
do
{
var message = string.IsNullOrEmpty(nextLink)
? CreateGetPetsRequest()
: CreateGetPetsNextPageRequest(nextLink);
var page = LowLevelPageableHelpers.ProcessMessage(Pipeline, message, _clientDiagnostics, context, "value", "nextLink");
nextLink = page.ContinuationToken;
yield return page;
} while (!string.IsNullOrEmpty(nextLink));
}
}

internal HttpMessage CreateGetPetRequest(long id)
{
var message = Pipeline.CreateMessage();
var request = message.Request;
request.Method = RequestMethod.Get;
var uri = new RawRequestUriBuilder();
uri.Reset(_endpoint);
uri.AppendPath("/pets/", false);
uri.AppendPath(id, true);
request.Uri = uri;
request.Headers.Add("Accept", "application/json, text/json");
message.ResponseClassifier = ResponseClassifier200.Instance;
return message;
}

internal HttpMessage CreateGetPetsRequest()
{
var message = Pipeline.CreateMessage();
var request = message.Request;
request.Method = RequestMethod.Get;
var uri = new RawRequestUriBuilder();
uri.Reset(_endpoint);
uri.AppendPath("/pets", false);
request.Uri = uri;
request.Headers.Add("Accept", "application/json, text/json");
message.ResponseClassifier = ResponseClassifier200.Instance;
return message;
}

internal HttpMessage CreateGetPetsNextPageRequest(string nextLink)
{
var message = Pipeline.CreateMessage();
var request = message.Request;
request.Method = RequestMethod.Get;
var uri = new RawRequestUriBuilder();
uri.Reset(_endpoint);
uri.AppendRawNextLink(nextLink, false);
request.Uri = uri;
request.Headers.Add("Accept", "application/json, text/json");
message.ResponseClassifier = ResponseClassifier200.Instance;
return message;
}

private sealed class ResponseClassifier200 : ResponseClassifier
{
private static ResponseClassifier _instance;
public static ResponseClassifier Instance => _instance ??= new ResponseClassifier200();
public override bool IsErrorResponse(HttpMessage message)
{
switch (message.Response.Status)
return message.Response.Status switch
{
case 200:
return false;
default:
return true;
}
200 => false,
_ => true
};
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#nullable disable

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Core.Experimental.Tests.Models;
using Azure.Core.Pipeline;
using Azure;
using System.Linq;

namespace Azure.Core.Experimental.Tests
{
/// <summary> The PetStore service client. </summary>
public partial class PetStoreClient
{
public static Pet GetPetFromBinaryData(BinaryData data)
{
return data;
}

// public virtual AsyncPageable<BinaryData> GetPetsAsync()
//#pragma warning restore AZC0002
// {
// // TODO: handle need for continuation token and
// AsyncPageable<BinaryData> pets = GetPetsAsync(new());
// pets.AsPages()

// //return PageableHelpers.create(i => { pets.AsPages}, _clientDiagnostics, "PetStoreClient.GetPets");
// //async IAsyncEnumerable<Page<BinaryData>> CreateEnumerableAsync(string nextLink, int? pageSizeHint, [EnumeratorCancellation] CancellationToken cancellationToken = default)
// //{
// // do
// // {
// // var message = string.IsNullOrEmpty(nextLink)
// // ? CreateGetPetsRequest()
// // : CreateGetPetsNextPageRequest(nextLink);
// // var page = await LowLevelPageableHelpers.ProcessMessageAsync(Pipeline, message, _clientDiagnostics, options, "value", "nextLink", cancellationToken).ConfigureAwait(false);
// // nextLink = page.ContinuationToken;
// // yield return page;
// // } while (!string.IsNullOrEmpty(nextLink));
// //}
// }

// TODO: extend to generic
private class PetPage<Pet> : Page<Pet>
{
private Page<BinaryData> _page;

public PetPage(Page<BinaryData> page)
{
_page = page;
}

//public override IReadOnlyList<Pet> Values => ()_page.Values.Select(data => GetPetFromBinaryData(data)).ToList().AsReadOnly();
//public override IReadOnlyList<Pet> Values => (IReadOnlyList<Pet>)_page.Values.Select(data => GetPetFromBinaryData(data));//.ToList().AsReadOnly();
public override IReadOnlyList<Pet> Values => (IReadOnlyList<Pet>)_page.Values.Select(data =>
{
// Pet pet = (Pet)data; // does not compile
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the weird part

return GetPetFromBinaryData(data);
});

public override string ContinuationToken => _page.ContinuationToken;

public override Response GetRawResponse() => _page.GetRawResponse();
}
}
}
69 changes: 69 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.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Core.Experimental.Tests;
Expand Down Expand Up @@ -211,6 +212,74 @@ public void ThrowOnErrorThrowsOnError()
});
}

[Test]
public async Task CanGetPageableResponse_LlcMethodAsync()
{
var page1Response = new MockResponse(200);
page1Response.SetContent(
@"{
""value"": [
{ ""name"": ""snoopy"", ""species"": ""beagle"" },
{ ""name"": ""lassie"", ""species"": ""collie"" }
],
""nextLink"": ""https://example.petstore.com""
}");

var page2Response = new MockResponse(200);
page2Response.SetContent(
@"{
""value"": [
{ ""name"": ""rintintin"", ""species"": ""german shepherd"" }
]
}");

var mockTransport = new MockTransport(page1Response, page2Response);
PetStoreClient client = CreateClient(mockTransport);

AsyncPageable<BinaryData> pets = client.GetPetsAsync(new());
int count = 0;
await foreach (var pet in pets)
{
count++;
}

Assert.AreEqual(3, count);
}

//[Test]
//public async Task CanGetPageableResponse_GrowUpHelperMethodAsync()
//{
// var page1Response = new MockResponse(200);
// page1Response.SetContent(
// @"{
// ""value"": [
// { ""name"": ""snoopy"", ""species"": ""beagle"" },
// { ""name"": ""lassie"", ""species"": ""collie"" }
// ],
// ""nextLink"": ""https://example.petstore.com""
// }");

// var page2Response = new MockResponse(200);
// page2Response.SetContent(
// @"{
// ""value"": [
// { ""name"": ""rintintin"", ""species"": ""german shepherd"" }
// ]
// }");

// var mockTransport = new MockTransport(page1Response, page2Response);
// PetStoreClient client = CreateClient(mockTransport);

// AsyncPageable<Pet> pets = client.GetPetsAsync();
// int count = 0;
// await foreach (var pet in pets)
// {
// count++;
// }

// Assert.AreEqual(3, count);
//}

#region Helpers
private void SerializePet(ref Utf8JsonWriter writer, Pet pet)
{
Expand Down