Skip to content

Commit

Permalink
support custom correlation id provider (#305)
Browse files Browse the repository at this point in the history
  • Loading branch information
jenschude authored May 15, 2024
1 parent e6dce91 commit 596e077
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Linq;
using commercetools.Base.Client;
using commercetools.Base.Client.Middlewares;
using commercetools.Sdk.Api;
using commercetools.Sdk.Api.Client;
using commercetools.Sdk.ImportApi;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace commercetools.Api.IntegrationTests;

public class CorrelationIdProviderTest
{
[Fact]
public async void TestCustomCorrelationId()
{
var configuration = new ConfigurationBuilder().
AddJsonFile("appsettings.test.Development.json", true).
AddEnvironmentVariables().
AddUserSecrets<ServiceProviderFixture>().
AddEnvironmentVariables("CTP_").
Build();

var s = new ServiceCollection();
s.UseCommercetoolsApi(configuration, "Client");
s.AddSingleton<ICorrelationIdProvider>(new TestCorrelationIdProvider());
var p = s.BuildServiceProvider();

var apiRoot = p.GetService<ProjectApiRoot>();

var result = await apiRoot.Get().SendAsync();

Assert.StartsWith("TestProvider/", result.HttpHeaders.GetValues(ApiHttpHeaders.X_CORRELATION_ID).First());
}

[Fact]
public async void TestCorrelationId()
{
var configuration = new ConfigurationBuilder().
AddJsonFile("appsettings.test.Development.json", true).
AddEnvironmentVariables().
AddUserSecrets<ServiceProviderFixture>().
AddEnvironmentVariables("CTP_").
Build();

var s = new ServiceCollection();
s.UseCommercetoolsApi(configuration, "Client");
var p = s.BuildServiceProvider();
var clientConfiguration = configuration.GetSection("Client").Get<ClientConfiguration>();
var apiRoot = p.GetService<ProjectApiRoot>();

var result = await apiRoot.Get().SendAsync();

Assert.StartsWith(clientConfiguration.ProjectKey, result.HttpHeaders.GetValues(ApiHttpHeaders.X_CORRELATION_ID).First());
}

[Fact]
public async void TestCorrelationIdPerRequest()
{
var configuration = new ConfigurationBuilder().
AddJsonFile("appsettings.test.Development.json", true).
AddEnvironmentVariables().
AddUserSecrets<ServiceProviderFixture>().
AddEnvironmentVariables("CTP_").
Build();

var s = new ServiceCollection();
s.UseCommercetoolsApi(configuration, "Client");
var p = s.BuildServiceProvider();

var apiRoot = p.GetService<ProjectApiRoot>();

ApiHttpHeaders headers = new ApiHttpHeaders();
headers.AddHeader(ApiHttpHeaders.X_CORRELATION_ID, $"TestRequest/{Guid.NewGuid()}");
var result = await apiRoot.Get().WithHeaders(headers).SendAsync();

Assert.StartsWith("TestRequest/", result.HttpHeaders.GetValues(ApiHttpHeaders.X_CORRELATION_ID).First());
}

private class TestCorrelationIdProvider : ICorrelationIdProvider
{
public string CorrelationId => $"TestProvider/{Guid.NewGuid()}";
public IClientConfiguration ClientConfiguration { get; set; }
}
}
11 changes: 6 additions & 5 deletions commercetools.Sdk/commercetools.Base.Client/ClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,27 @@ public static IClient Create(
IHttpClientFactory factory,
ISerializerService serializerService,
ITokenProvider tokenProvider,
bool readResponseAsStream = false)
bool readResponseAsStream = false,
ICorrelationIdProvider correlationIdProvider = null)
{
Validator.ValidateObject(configuration, new ValidationContext(configuration), true);
if (readResponseAsStream && serializerService is IStreamSerializerService streamSerializer)
{
return new StreamCtpClient(
CreateMiddlewareStack(clientName, configuration, factory, tokenProvider, true),
CreateMiddlewareStack(clientName, configuration, factory, tokenProvider, true, correlationIdProvider),
streamSerializer,
clientName
);
}
return new CtpClient(
CreateMiddlewareStack(clientName, configuration, factory, tokenProvider),
CreateMiddlewareStack(clientName, configuration, factory, tokenProvider, false, correlationIdProvider),
serializerService,
clientName
);
}

public static Middleware CreateMiddlewareStack(string clientName, IClientConfiguration configuration,
IHttpClientFactory factory, ITokenProvider tokenProvider, bool readResponseAsStream = false)
IHttpClientFactory factory, ITokenProvider tokenProvider, bool readResponseAsStream = false, ICorrelationIdProvider correlationIdProvider = null)
{
var httpClient = factory.CreateClient(clientName);
httpClient.BaseAddress = new Uri(configuration.ApiBaseAddress);
Expand All @@ -44,7 +45,7 @@ public static Middleware CreateMiddlewareStack(string clientName, IClientConfigu
{
CreateAuthMiddleware(tokenProvider),
CreateCorrelationIdMiddleware(
new DefaultCorrelationIdProvider(configuration)
correlationIdProvider ?? new DefaultCorrelationIdProvider(configuration)
)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,22 @@ private static IDictionary<string, IHttpClientBuilder> UseMultipleClients(this I
{
var builders = new ConcurrentDictionary<string, IHttpClientBuilder>();


clients.ToList().ForEach(clientName =>
{
IClientConfiguration clientConfiguration =
configuration.GetSection(clientName).Get<ClientConfiguration>();
Validator.ValidateObject(clientConfiguration, new ValidationContext(clientConfiguration), true);

builders.TryAdd(clientName, services.SetupClient(clientName, errorResponseTypeMapper, serializerFactory, options));
services.AddSingleton(serviceProvider =>
{
var client = ClientFactory.Create(clientName, clientConfiguration,
serviceProvider.GetService<IHttpClientFactory>(),
serializerFactory(serviceProvider),
tokenProviderSupplier(clientName, configuration, serviceProvider),
options.ReadResponseAsStream);
options.ReadResponseAsStream,
serviceProvider.GetService<ICorrelationIdProvider>());
client.Name = clientName;
return client;
});
Expand All @@ -83,7 +85,9 @@ private static IDictionary<string, IHttpClientBuilder> UseSingleClient(this ISer
serviceProvider.GetService<IHttpClientFactory>(),
serializerFactory(serviceProvider),
tokenProviderSupplier(clientName, configuration, serviceProvider),
options.ReadResponseAsStream);
options.ReadResponseAsStream,
serviceProvider.GetService<ICorrelationIdProvider>());

client.Name = clientName;
return client;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ public CorrelationIdMiddleware(ICorrelationIdProvider correlationIdProvider)

protected internal override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var correlationId = this.correlationIdProvider.CorrelationId;
request.Headers.Add("X-Correlation-ID", correlationId);
if (!request.Headers.Contains(ApiHttpHeaders.X_CORRELATION_ID))
{
request.Headers.Add(ApiHttpHeaders.X_CORRELATION_ID, this.correlationIdProvider.CorrelationId);
}
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
Expand Down

0 comments on commit 596e077

Please sign in to comment.