Skip to content

Commit ab8a358

Browse files
iancooperclaude
andcommitted
fix: case-insensitive SessionId and reserved-header handling for ASB (#4054)
Brighter's JSON serialization camelCases header bag keys, so a "SessionId" key returns as "sessionId" after an Outbox round-trip. The publisher's exact-match lookup missed it (session never set) and the case-sensitive reserved-header filter let it leak into ApplicationProperties. Both lookups are now OrdinalIgnoreCase. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b142ad8 commit ab8a358

2 files changed

Lines changed: 46 additions & 4 deletions

File tree

src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusMessagePublisher.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System;
2+
using System.Linq;
23
using System.Net.Mime;
34
using Azure.Messaging.ServiceBus;
45
using Paramore.Brighter.Extensions;
@@ -59,11 +60,17 @@ private static void AddBrighterHeaders(Message message, ServiceBusMessage azureS
5960
azureServiceBusMessage.CorrelationId = message.Header.CorrelationId;
6061
if (!string.IsNullOrEmpty(message.Header.ReplyTo!))
6162
azureServiceBusMessage.ReplyTo = message.Header.ReplyTo?.Value;
62-
if (message.Header.Bag.TryGetValue(ASBConstants.SessionIdKey, out object? value))
63-
azureServiceBusMessage.SessionId = value.ToString();
63+
//Brighter's JSON serialization camelCases bag keys (JsonNamingPolicy.CamelCase), so a key
64+
//written as "SessionId" returns as "sessionId" after a round-trip (e.g. via an Outbox).
65+
//Resolve the SessionId regardless of casing.
66+
var sessionId = message.Header.Bag
67+
.FirstOrDefault(h => string.Equals(h.Key, ASBConstants.SessionIdKey, StringComparison.OrdinalIgnoreCase))
68+
.Value;
69+
if (sessionId is not null)
70+
azureServiceBusMessage.SessionId = sessionId.ToString();
6471

6572
foreach (var header in message.Header.Bag.Where(h =>
66-
!ASBConstants.ReservedHeaders.Contains(h.Key)
73+
!ASBConstants.ReservedHeaders.Contains(h.Key, StringComparer.OrdinalIgnoreCase)
6774
&& !MessageHeader.IsLocalHeader(h.Key)))
6875
{
6976
azureServiceBusMessage.ApplicationProperties[header.Key] = header.Value;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using Paramore.Brighter.MessagingGateway.AzureServiceBus;
3+
using Xunit;
4+
5+
namespace Paramore.Brighter.AzureServiceBus.Tests.MessagingGateway;
6+
7+
[Trait("Category", "ASB")]
8+
public class AzureServiceBusMessagePublisherSessionIdTests
9+
{
10+
[Theory]
11+
[InlineData("SessionId")] // as written by application code
12+
[InlineData("sessionId")] // as it returns from a camelCasing serialization round-trip (e.g. via the Outbox)
13+
public void When_Converting_A_Message_With_A_SessionId_Bag_Key_Of_Any_Casing_The_SessionId_Is_Set(string sessionIdKey)
14+
{
15+
// Brighter's JSON serialization uses JsonNamingPolicy.CamelCase, so a bag key written as
16+
// "SessionId" comes back as "sessionId" once the message round-trips through serialization
17+
// (for example when stored in and read back from an Outbox). The publisher must resolve the
18+
// SessionId regardless of the key's casing — and the reserved key must not leak onto the wire.
19+
const string expectedSessionId = "order-42";
20+
var header = new MessageHeader(
21+
messageId: Guid.NewGuid().ToString(),
22+
topic: new RoutingKey("test.topic"),
23+
messageType: MessageType.MT_COMMAND);
24+
header.Bag[sessionIdKey] = expectedSessionId;
25+
26+
var message = new Message(header, new MessageBody("body"));
27+
28+
var asbMessage = AzureServiceBusMessagePublisher.ConvertToServiceBusMessage(message);
29+
30+
// the session id is set on the outgoing message...
31+
Assert.Equal(expectedSessionId, asbMessage.SessionId);
32+
// ...and the reserved header does not leak into ApplicationProperties
33+
Assert.False(asbMessage.ApplicationProperties.ContainsKey(sessionIdKey));
34+
}
35+
}

0 commit comments

Comments
 (0)