Changing msgpack options (#20031)

This commit is contained in:
TeBeCo 2020-04-03 02:41:40 +02:00 committed by GitHub
parent f17520c6f0
commit c01c8dd476
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 44 deletions

View File

@ -9,24 +9,31 @@ namespace Microsoft.AspNetCore.SignalR
{ {
public class MessagePackHubProtocolOptions public class MessagePackHubProtocolOptions
{ {
private IList<IFormatterResolver> _formatterResolvers; private MessagePackSerializerOptions _messagePackSerializerOptions;
public IList<IFormatterResolver> FormatterResolvers /// <summary>
/// <para>Gets or sets the <see cref="MessagePackSerializerOptions"/> used internally by the <see cref="MessagePackSerializer" />.</para>
/// <para>If you override the default value, we strongly recommend that you set <see cref="MessagePackSecurity" /> to <see cref="MessagePackSecurity.UntrustedData"/> by calling:</para>
/// <code>customMessagePackSerializerOptions = customMessagePackSerializerOptions.WithSecurity(MessagePackSecurity.UntrustedData)</code>
/// If you modify the default options you must also assign the updated options back to the <see cref="SerializerOptions" /> property:
/// <code>options.SerializerOptions = options.SerializerOptions.WithResolver(new CustomResolver());</code>
/// </summary>
public MessagePackSerializerOptions SerializerOptions
{ {
get get
{ {
if (_formatterResolvers == null) if (_messagePackSerializerOptions == null)
{ {
// The default set of resolvers trigger a static constructor that throws on AOT environments. // The default set of resolvers trigger a static constructor that throws on AOT environments.
// This gives users the chance to use an AOT friendly formatter. // This gives users the chance to use an AOT friendly formatter.
_formatterResolvers = MessagePackHubProtocol.CreateDefaultFormatterResolvers(); _messagePackSerializerOptions = MessagePackHubProtocol.CreateDefaultMessagePackSerializerOptions();
} }
return _formatterResolvers; return _messagePackSerializerOptions;
} }
set set
{ {
_formatterResolvers = value; _messagePackSerializerOptions = value;
} }
} }
} }

View File

@ -27,6 +27,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
private const int NonVoidResult = 3; private const int NonVoidResult = 3;
private readonly MessagePackSerializerOptions _msgPackSerializerOptions; private readonly MessagePackSerializerOptions _msgPackSerializerOptions;
private static readonly string ProtocolName = "messagepack"; private static readonly string ProtocolName = "messagepack";
private static readonly int ProtocolVersion = 1; private static readonly int ProtocolVersion = 1;
@ -52,37 +53,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
/// <param name="options">The options used to initialize the protocol.</param> /// <param name="options">The options used to initialize the protocol.</param>
public MessagePackHubProtocol(IOptions<MessagePackHubProtocolOptions> options) public MessagePackHubProtocol(IOptions<MessagePackHubProtocolOptions> options)
{ {
var msgPackOptions = options.Value; _msgPackSerializerOptions = options.Value.SerializerOptions;
var resolver = SignalRResolver.Instance;
var hasCustomFormatterResolver = false;
// if counts don't match then we know users customized resolvers so we set up the options with the provided resolvers
if (msgPackOptions.FormatterResolvers.Count != SignalRResolver.Resolvers.Count)
{
hasCustomFormatterResolver = true;
}
else
{
// Compare each "reference" in the FormatterResolvers IList<> against the default "SignalRResolver.Resolvers" IList<>
for (var i = 0; i < msgPackOptions.FormatterResolvers.Count; i++)
{
// check if the user customized the resolvers
if (msgPackOptions.FormatterResolvers[i] != SignalRResolver.Resolvers[i])
{
hasCustomFormatterResolver = true;
break;
}
}
}
if (hasCustomFormatterResolver)
{
resolver = CompositeResolver.Create(Array.Empty<IMessagePackFormatter>(), (IReadOnlyList<IFormatterResolver>)msgPackOptions.FormatterResolvers);
}
_msgPackSerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(resolver)
.WithSecurity(MessagePackSecurity.UntrustedData);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -656,17 +627,17 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
} }
} }
internal static List<IFormatterResolver> CreateDefaultFormatterResolvers() internal static MessagePackSerializerOptions CreateDefaultMessagePackSerializerOptions() =>
{ MessagePackSerializerOptions
// Copy to allow users to add/remove resolvers without changing the static SignalRResolver list .Standard
return new List<IFormatterResolver>(SignalRResolver.Resolvers); .WithResolver(SignalRResolver.Instance)
} .WithSecurity(MessagePackSecurity.UntrustedData);
internal class SignalRResolver : IFormatterResolver internal class SignalRResolver : IFormatterResolver
{ {
public static readonly IFormatterResolver Instance = new SignalRResolver(); public static readonly IFormatterResolver Instance = new SignalRResolver();
public static readonly IList<IFormatterResolver> Resolvers = new IFormatterResolver[] public static readonly IReadOnlyList<IFormatterResolver> Resolvers = new IFormatterResolver[]
{ {
DynamicEnumAsStringResolver.Instance, DynamicEnumAsStringResolver.Instance,
ContractlessStandardResolver.Instance, ContractlessStandardResolver.Instance,

View File

@ -14,6 +14,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MessagePack; using MessagePack;
using MessagePack.Formatters; using MessagePack.Formatters;
using MessagePack.Resolvers;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -2371,7 +2372,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
services.AddSignalR() services.AddSignalR()
.AddMessagePackProtocol(options => .AddMessagePackProtocol(options =>
{ {
options.FormatterResolvers.Insert(0, new CustomFormatter()); options.SerializerOptions = MessagePackSerializerOptions.Standard.WithResolver(CompositeResolver.Create(new CustomFormatter(), options.SerializerOptions.Resolver));
}); });
}, LoggerFactory); }, LoggerFactory);