-
Notifications
You must be signed in to change notification settings - Fork 647
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Disable type inference from message content (#6274)
- Loading branch information
1 parent
7476f1f
commit 9263070
Showing
9 changed files
with
272 additions
and
18 deletions.
There are no files selected for viewing
135 changes: 135 additions & 0 deletions
135
src/NServiceBus.AcceptanceTests/Serialization/When_disabling_serializer_type_inference.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
namespace NServiceBus.AcceptanceTests.Serialization | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using AcceptanceTesting; | ||
using EndpointTemplates; | ||
using MessageInterfaces; | ||
using NServiceBus.Pipeline; | ||
using NServiceBus.Serialization; | ||
using NUnit.Framework; | ||
using Settings; | ||
|
||
class When_disabling_serializer_type_inference : NServiceBusAcceptanceTest | ||
{ | ||
[Test] | ||
public async Task Should_not_deserialize_messages_without_types_header() | ||
{ | ||
var context = await Scenario.Define<Context>() | ||
.WithEndpoint<ReceivingEndpoint>(e => e | ||
.DoNotFailOnErrorMessages() | ||
.When(s => s.SendLocal(new MessageWithoutTypeHeader()))) | ||
.Done(c => c.IncomingMessageReceived) | ||
.Run(TimeSpan.FromSeconds(20)); | ||
|
||
Assert.IsFalse(context.HandlerInvoked); | ||
Assert.AreEqual(1, context.FailedMessages.Single().Value.Count); | ||
Exception exception = context.FailedMessages.Single().Value.Single().Exception; | ||
Assert.IsInstanceOf<MessageDeserializationException>(exception); | ||
StringAssert.Contains($"Could not determine the message type from the '{Headers.EnclosedMessageTypes}' header", exception.InnerException.Message); | ||
} | ||
|
||
[Test] | ||
public async Task Should_not_deserialize_messages_with_unknown_type_header() | ||
{ | ||
var context = await Scenario.Define<Context>() | ||
.WithEndpoint<ReceivingEndpoint>(e => e | ||
.DoNotFailOnErrorMessages() | ||
.When(s => s.SendLocal(new UnknownMessage()))) | ||
.Done(c => c.IncomingMessageReceived) | ||
.Run(TimeSpan.FromSeconds(20)); | ||
|
||
Assert.IsFalse(context.HandlerInvoked); | ||
Assert.AreEqual(1, context.FailedMessages.Single().Value.Count); | ||
Exception exception = context.FailedMessages.Single().Value.Single().Exception; | ||
Assert.IsInstanceOf<MessageDeserializationException>(exception); | ||
StringAssert.Contains($"Could not determine the message type from the '{Headers.EnclosedMessageTypes}' header", exception.InnerException.Message); | ||
} | ||
|
||
class Context : ScenarioContext | ||
{ | ||
public bool HandlerInvoked { get; set; } | ||
public bool IncomingMessageReceived { get; set; } | ||
} | ||
|
||
class ReceivingEndpoint : EndpointConfigurationBuilder | ||
{ | ||
public ReceivingEndpoint() => | ||
EndpointSetup<DefaultServer>(c => | ||
{ | ||
c.Pipeline.Register(typeof(TypeHeaderManipulationBehavior), "Removes the EnclosedMessageTypes header from incoming messages"); | ||
var serializerSettings = c.UseSerialization<CustomSerializer>(); | ||
serializerSettings.DisableMessageTypeInference(); | ||
}); | ||
|
||
public class MessageHandler : IHandleMessages<MessageWithoutTypeHeader> | ||
{ | ||
Context testContext; | ||
|
||
public MessageHandler(Context testContext) => this.testContext = testContext; | ||
|
||
public Task Handle(MessageWithoutTypeHeader message, IMessageHandlerContext context) | ||
{ | ||
testContext.HandlerInvoked = true; | ||
return Task.FromResult(0); | ||
} | ||
} | ||
|
||
class TypeHeaderManipulationBehavior : Behavior<IIncomingPhysicalMessageContext> | ||
{ | ||
Context testContext; | ||
|
||
public TypeHeaderManipulationBehavior(Context testContext) => this.testContext = testContext; | ||
|
||
public override Task Invoke(IIncomingPhysicalMessageContext context, Func<Task> next) | ||
{ | ||
testContext.IncomingMessageReceived = true; | ||
|
||
if (context.MessageHeaders[Headers.EnclosedMessageTypes].Contains(typeof(MessageWithoutTypeHeader).FullName)) | ||
{ | ||
context.Message.Headers.Remove(Headers.EnclosedMessageTypes); | ||
} | ||
else if (context.MessageHeaders[Headers.EnclosedMessageTypes].Contains(typeof(UnknownMessage).FullName)) | ||
{ | ||
context.Message.Headers[Headers.EnclosedMessageTypes] = "SomeNamespace.SomeMessageType"; | ||
} | ||
|
||
return next(); | ||
} | ||
} | ||
} | ||
|
||
public class MessageWithoutTypeHeader : IMessage | ||
{ | ||
} | ||
|
||
public class UnknownMessage : IMessage | ||
{ | ||
} | ||
|
||
class CustomSerializer : SerializationDefinition, IMessageSerializer | ||
{ | ||
public string ContentType { get; } = "CustomSerializer"; | ||
|
||
public void Serialize(object message, Stream stream) | ||
{ | ||
stream.WriteByte(42); // need to write some byte for message serialization to work | ||
} | ||
|
||
public object[] Deserialize(Stream stream, IList<Type> messageTypes = null) | ||
{ | ||
if (messageTypes?.Count > 0) | ||
{ | ||
throw new InvalidOperationException("Did not expect message types to be detected in this test"); | ||
} | ||
|
||
throw new InvalidOperationException("Should not invoke deserializer without type information"); | ||
} | ||
|
||
public override Func<IMessageMapper, IMessageSerializer> Configure(ReadOnlySettings settings) => _ => this; | ||
} | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
src/NServiceBus.AcceptanceTests/Serialization/When_message_type_header_is_whitespaces.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
namespace NServiceBus.AcceptanceTests.Serialization | ||
{ | ||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using AcceptanceTesting; | ||
using EndpointTemplates; | ||
using NServiceBus.Pipeline; | ||
using NUnit.Framework; | ||
|
||
public class When_message_type_header_is_whitespaces : NServiceBusAcceptanceTest | ||
{ | ||
[Test] | ||
public async Task Should_move_message_to_error_queue() | ||
{ | ||
var context = await Scenario.Define<Context>() | ||
.WithEndpoint<ReceivingEndpoint>(e => e | ||
.DoNotFailOnErrorMessages() | ||
.When(s => s.SendLocal(new MessageWithEmptyTypeHeader()))) | ||
.Done(c => c.IncomingMessageReceived) | ||
.Run(TimeSpan.FromSeconds(20)); | ||
|
||
Assert.IsFalse(context.HandlerInvoked); | ||
Assert.AreEqual(1, context.FailedMessages.Single().Value.Count); | ||
Exception exception = context.FailedMessages.Single().Value.Single().Exception; | ||
Assert.IsInstanceOf<MessageDeserializationException>(exception); | ||
} | ||
|
||
class Context : ScenarioContext | ||
{ | ||
public bool HandlerInvoked { get; set; } | ||
public bool IncomingMessageReceived { get; set; } | ||
} | ||
|
||
class ReceivingEndpoint : EndpointConfigurationBuilder | ||
{ | ||
public ReceivingEndpoint() => | ||
EndpointSetup<DefaultServer>(c => | ||
{ | ||
c.Pipeline.Register(typeof(TypeHeaderRemovingBehavior), "Removes the EnclosedMessageTypes header from incoming messages"); | ||
}); | ||
|
||
public class MessageHandler : IHandleMessages<MessageWithEmptyTypeHeader> | ||
{ | ||
Context testContext; | ||
|
||
public MessageHandler(Context testContext) => this.testContext = testContext; | ||
|
||
public Task Handle(MessageWithEmptyTypeHeader message, IMessageHandlerContext context) | ||
{ | ||
testContext.HandlerInvoked = true; | ||
return Task.FromResult(0); | ||
} | ||
} | ||
|
||
class TypeHeaderRemovingBehavior : Behavior<IIncomingPhysicalMessageContext> | ||
{ | ||
Context testContext; | ||
|
||
public TypeHeaderRemovingBehavior(Context testContext) => this.testContext = testContext; | ||
|
||
public override Task Invoke(IIncomingPhysicalMessageContext context, Func<Task> next) | ||
{ | ||
testContext.IncomingMessageReceived = true; | ||
|
||
// add some whitespace instead of removing the header completely | ||
context.Message.Headers[Headers.EnclosedMessageTypes] = " "; | ||
|
||
return next(); | ||
} | ||
} | ||
} | ||
|
||
public class MessageWithEmptyTypeHeader : IMessage | ||
{ | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/NServiceBus.Core/Serialization/SerializationExtensionsExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
namespace NServiceBus | ||
{ | ||
using Serialization; | ||
using Settings; | ||
|
||
/// <summary> | ||
/// Provides extensions methods for the <see cref="SerializationExtensions{T}"/> class. | ||
/// </summary> | ||
public static class SerializationExtensionsExtensions | ||
{ | ||
/// <summary> | ||
/// Disables inference of message type based on the content type if the message type can't be determined by the 'NServiceBus.EnclosedMessageTypes' header. | ||
/// </summary> | ||
public static void DisableMessageTypeInference<T>(this SerializationExtensions<T> config) where T : SerializationDefinition | ||
{ | ||
Guard.AgainstNull(nameof(config), config); | ||
|
||
config.EndpointConfigurationSettings.Set(DisableMessageTypeInferenceKey, true); | ||
} | ||
|
||
internal static bool IsMessageTypeInferenceEnabled(this ReadOnlySettings endpointConfigurationSettings) => | ||
!endpointConfigurationSettings.GetOrDefault<bool>(DisableMessageTypeInferenceKey); | ||
|
||
const string DisableMessageTypeInferenceKey = "NServiceBus.Serialization.DisableMessageTypeInference"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters