< Summary - AsyncResponse (Release / net8.0+net10.0 / unit+integration)

Information
Class: AsyncResponse.Transports.RabbitMQ.RabbitMqCorrelationIdExtractor
Assembly: AsyncResponse.Transports.RabbitMQ
File(s): /home/runner/work/AsyncResponse/AsyncResponse/src/Transports/AsyncResponse.Transports.RabbitMQ/RabbitMqCorrelationIdExtractor.cs
Line coverage
100%
Covered lines: 64
Uncovered lines: 0
Coverable lines: 64
Total lines: 123
Line coverage: 100%
Branch coverage
100%
Covered branches: 60
Total branches: 60
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Extract(...)100%2424100%
TryConvertHeader(...)100%88100%
TryReadPath(...)100%1212100%
TryGetProperty(...)100%66100%
UnwrapJsonString(...)100%1010100%

File(s)

/home/runner/work/AsyncResponse/AsyncResponse/src/Transports/AsyncResponse.Transports.RabbitMQ/RabbitMqCorrelationIdExtractor.cs

#LineLine coverage
 1using RabbitMQ.Client;
 2using System.Text;
 3using System.Text.Json;
 4using System.Text.Json.Nodes;
 5
 6namespace AsyncResponse.Transports.RabbitMQ;
 7
 8internal static class RabbitMqCorrelationIdExtractor
 9{
 10    /// <summary>Extracts the correlation id from the supplied message.</summary>
 11    public static string? Extract(
 12        RabbitMqDelivery delivery,
 13        string messageJson,
 14        RabbitMqAsyncResponseOptions options)
 15    {
 316        if (!string.IsNullOrWhiteSpace(delivery.BasicProperties.CorrelationId))
 317            return delivery.BasicProperties.CorrelationId;
 18
 319        if (!string.IsNullOrWhiteSpace(options.CorrelationIdHeader)
 320            && delivery.BasicProperties.Headers is not null
 321            && delivery.BasicProperties.Headers.TryGetValue(options.CorrelationIdHeader, out var header)
 322            && TryConvertHeader(header) is { } headerValue
 323            && !string.IsNullOrWhiteSpace(headerValue))
 24        {
 325            return headerValue;
 26        }
 27
 328        var jsonPaths = options.CorrelationIdJsonPaths;
 329        if (jsonPaths is null || jsonPaths.Length == 0 || string.IsNullOrWhiteSpace(messageJson))
 330            return null;
 31
 32        JsonNode? root;
 33        try
 34        {
 335            root = JsonNode.Parse(messageJson);
 336        }
 337        catch (JsonException)
 38        {
 339            return null;
 40        }
 41
 342        if (root is null)
 343            return null;
 44
 345        foreach (var path in jsonPaths)
 46        {
 347            var value = TryReadPath(root, path);
 348            if (!string.IsNullOrWhiteSpace(value))
 349                return value;
 50        }
 51
 252        return null;
 253    }
 54
 55    private static string? TryConvertHeader(object? header)
 256        => header switch
 257        {
 258            null => null,
 259            string s => s,
 260            byte[] bytes => Encoding.UTF8.GetString(bytes),
 261            ReadOnlyMemory<byte> memory => Encoding.UTF8.GetString(memory.Span),
 262            _ => header.ToString()
 263        };
 64
 65    private static string? TryReadPath(JsonNode root, string path)
 66    {
 367        if (string.IsNullOrWhiteSpace(path))
 368            return null;
 69
 370        var current = root;
 371        foreach (var segment in path.Split('.', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
 72        {
 373            current = UnwrapJsonString(current);
 374            if (current is not JsonObject obj)
 375                return null;
 76
 377            current = TryGetProperty(obj, segment);
 378            if (current is null)
 379                return null;
 80        }
 81
 382        current = UnwrapJsonString(current);
 383        return current switch
 384        {
 385            JsonValue value when value.TryGetValue<string>(out var s) => s,
 286            JsonValue value => value.ToString(),
 387            _ => null
 388        };
 89    }
 90
 91    private static JsonNode? TryGetProperty(JsonObject obj, string name)
 92    {
 393        if (obj.TryGetPropertyValue(name, out var exact))
 394            return exact;
 95
 296        foreach (var property in obj)
 97        {
 298            if (string.Equals(property.Key, name, StringComparison.OrdinalIgnoreCase))
 299                return property.Value;
 100        }
 101
 2102        return null;
 3103    }
 104
 105    private static JsonNode? UnwrapJsonString(JsonNode? node)
 106    {
 3107        if (node is not JsonValue value || !value.TryGetValue<string>(out var text))
 3108            return node;
 109
 3110        var trimmed = text.AsSpan().TrimStart();
 3111        if (trimmed.Length == 0 || (trimmed[0] != '{' && trimmed[0] != '['))
 3112            return node;
 113
 114        try
 115        {
 2116            return JsonNode.Parse(text);
 117        }
 2118        catch (JsonException)
 119        {
 2120            return node;
 121        }
 3122    }
 123}