Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: remove default value from CorrelateOptions.RequestHeaders #129

Merged
merged 1 commit into from
Dec 17, 2024
Merged
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
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
<NoWarn>$(NoWarn);IDE0079;S1135;CA1510;CA1511;CA1512;CA1513;CA1863</NoWarn>
<NoWarn>$(NoWarn);IDE0079;S1135;CA1510;CA1511;CA1512;CA1513;CA1863;xUnit1042</NoWarn>
<NoWarn Condition="'$(Configuration)'=='Release'">$(NoWarn);NETSDK1138</NoWarn>
<WarningsAsErrors>$(WarningsAsErrors);NU1601;NU1603;NU1605;NU1608;NU1701;MSB3644</WarningsAsErrors>
<ContinuousIntegrationBuild Condition="'$(CI)'!=''">true</ContinuousIntegrationBuild>
Expand Down
5 changes: 3 additions & 2 deletions src/Correlate.AspNetCore/AspNetCore/CorrelateFeature.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Correlate.Http.Extensions;
using Correlate.Http;
using Correlate.Http.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
Expand Down Expand Up @@ -88,7 +89,7 @@ public void StopCorrelating(HttpContext httpContext)

private (string? headerName, string correlationId) GetOrCreateCorrelationHeaderAndId(HttpContext httpContext)
{
(string requestHeaderName, string? requestCorrelationId) = httpContext.Request.Headers.GetCorrelationIdHeader(_options.RequestHeaders);
(string requestHeaderName, string? requestCorrelationId) = httpContext.Request.Headers.GetCorrelationIdHeader(_options.RequestHeaders ?? [CorrelationHttpHeaders.CorrelationId]);
if (requestCorrelationId is not null)
{
LogRequestHeaderFound(_logger, requestHeaderName, requestCorrelationId, null);
Expand Down
22 changes: 8 additions & 14 deletions src/Correlate.AspNetCore/AspNetCore/CorrelateOptions.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
using Correlate.Http;

namespace Correlate.AspNetCore;
namespace Correlate.AspNetCore;

/// <summary>
/// Options for handling correlation id on incoming requests.
/// </summary>
public sealed class CorrelateOptions: CorrelationManagerOptions
public sealed class CorrelateOptions : CorrelationManagerOptions
{
private static readonly string[] DefaultRequestHeaders = { CorrelationHttpHeaders.CorrelationId };

private string[]? _requestHeaders;

/// <summary>
/// Gets or sets the request headers to retrieve the correlation id from. Defaults to <c>X-Correlation-ID</c>.
/// Gets or sets the request headers to retrieve the correlation id from.
/// <para>
/// To disable using the correlation ID from an incoming request, explicitly set this to an empty list.
/// When <see langword="null" />, internally defaults to <c>["X-Correlation-ID"]</c>.
/// </para>
/// </summary>
/// <remarks>
/// The first matching request header will be used.
/// </remarks>
public string[] RequestHeaders
{
get => _requestHeaders ?? DefaultRequestHeaders;
set => _requestHeaders = value;
}
public IReadOnlyList<string>? RequestHeaders { get; set; }

/// <summary>
/// Gets or sets whether to include the correlation id in the response.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Correlate.Http.Extensions;

internal static class HeaderDictionaryExtensions
{
internal static KeyValuePair<string, string?> GetCorrelationIdHeader(this IDictionary<string, StringValues> httpHeaders, ICollection<string> acceptedHeaders)
internal static KeyValuePair<string, string?> GetCorrelationIdHeader(this IDictionary<string, StringValues> httpHeaders, IReadOnlyCollection<string> acceptedHeaders)
{
if (acceptedHeaders is null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public CorrelateFeatureTests()
_correlationIdFactory = Substitute.For<ICorrelationIdFactory>();
_correlationIdFactory.Create().Returns(CorrelationId);

_options = new CorrelateOptions();
_options = new CorrelateOptions { RequestHeaders = [CorrelationHttpHeaders.CorrelationId] };
_sut = new CorrelateFeature(
_services.GetRequiredService<ILoggerFactory>(),
_correlationIdFactory,
Expand All @@ -67,11 +67,11 @@ public async Task Given_that_correlating_has_started_when_firing_to_send_headers
_options.RequestHeaders.Should().NotBeNullOrEmpty();
if (requestHeader is not null)
{
_options.RequestHeaders = new[] { requestHeader };
_options.RequestHeaders = [requestHeader];
}

var expectedHeader = new KeyValuePair<string, StringValues>(
_options.RequestHeaders[0],
_options.RequestHeaders![0],
new StringValues(CorrelationId)
);

Expand All @@ -91,7 +91,7 @@ public async Task Given_that_correlating_has_started_when_firing_to_send_headers
[InlineData(CorrelationHttpHeaders.RequestId)]
public async Task Given_that_request_contains_correlationId_header_in_allowed_list_when_correlating_has_started_it_should_have_used_that_correlationId(string headerName)
{
_options.RequestHeaders = new[] { CorrelationHttpHeaders.CorrelationId, CorrelationHttpHeaders.RequestId };
_options.RequestHeaders = [CorrelationHttpHeaders.CorrelationId, CorrelationHttpHeaders.RequestId];

string correlationId = Guid.NewGuid().ToString("D");
_httpContext.Features.Get<IHttpRequestFeature>()!
Expand Down Expand Up @@ -203,7 +203,7 @@ public async Task Given_that_response_already_contains_correlation_header_when_f
_options.RequestHeaders.Should().NotBeNullOrEmpty();

const string existingCorrelationId = "existing-id";
_responseFeature.Headers.Append(_options.RequestHeaders[0], existingCorrelationId);
_responseFeature.Headers.Append(_options.RequestHeaders![0], existingCorrelationId);

var expectedHeader = new KeyValuePair<string, StringValues>(
_options.RequestHeaders[0],
Expand Down
52 changes: 50 additions & 2 deletions test/Correlate.AspNetCore.Tests/AspNetCore/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void Dispose()
public async Task Given_custom_header_is_defined_when_executing_request_the_response_should_contain_custom_header()
{
const string headerName = "my-header";
_options.RequestHeaders = new[] { headerName };
_options.RequestHeaders = [headerName];

// Act
HttpClient client = _factory.CreateClient();
Expand Down Expand Up @@ -90,7 +90,7 @@ public async Task Given_default_configuration_when_executing_request_the_respons
[Fact]
public async Task Given_no_headers_are_defined_when_executing_request_the_response_should_contain_default_header()
{
_options.RequestHeaders = Array.Empty<string>();
_options.RequestHeaders = [];

// Act
HttpClient client = _factory.CreateClient();
Expand Down Expand Up @@ -241,4 +241,52 @@ public async Task When_logging_should_have_correlationId_for_all_logged_events()
.ContainEquivalentOf(new LoggerExtensions.CorrelatedLogScope(CorrelateConstants.CorrelationIdKey, correlationId))
);
}

[Theory]
[MemberData(nameof(GetOptionBindingTestCases))]
public void Options_should_deserialize_from_config(Dictionary<string, string?> configDict, CorrelateOptions expectedOptions)
{
IConfigurationRoot config = new ConfigurationBuilder()
.AddInMemoryCollection(configDict)
.Build();

// Act
using ServiceProvider services = new ServiceCollection()
.Configure<CorrelateOptions>(config.Bind)
.BuildServiceProvider();

// Assert
CorrelateOptions opts = services.GetRequiredService<IOptions<CorrelateOptions>>().Value;
opts.Should().BeEquivalentTo(expectedOptions);
}

public static IEnumerable<object[]> GetOptionBindingTestCases()
{
yield return
[
new Dictionary<string, string?>(),
new CorrelateOptions
{
IncludeInResponse = true,
LoggingScopeKey = CorrelateConstants.CorrelationIdKey,
RequestHeaders = null
}
];
yield return
[
new Dictionary<string, string?>
{
{ "LoggingScopeKey", "LogKey1" },
{ "IncludeInResponse", "false" },
{ "RequestHeaders:0", "Header1" },
{ "RequestHeaders:1", "Header2" }
},
new CorrelateOptions
{
LoggingScopeKey = "LogKey1",
IncludeInResponse = false,
RequestHeaders = ["Header1", "Header2"]
}
];
}
}
Loading