Как добавить заголовок сообщения в запрос при использовании клиента по умолчанию из сервисной фабрики Azure?

Мне интересно, можно ли добавить пользовательский заголовок сообщения в исходящий запрос для переноса дополнительной информации без десериализации полезной нагрузки для полного выполнения таких функций, как аутентификация, проверка или сопоставление запроса, такого как wcf, предоставляемого с помощью messagesinspector?

2 ответа

Решение

Обновить

С SDK v2 вы теперь (относительно) можете легко изменять заголовки как надежных служб, так и субъектов. Обратите внимание, что в приведенных ниже примерах некоторые элементы-оболочки были опущены для краткости.

клиент

Мы используем ServiceProxyFactory создавать прокси вместо статических ServiceProxy, Тогда мы можем обернуть IServiceRemotingClientFactory а также IServiceRemotingClient и перехватывать сервисные звонки. То же самое можно сделать с ActorProxyFactory, Обратите внимание, что это переопределяет поведение атрибутов, таких как WcfServiceRemotingProviderAttribute, поскольку мы явно указываем клиентскую фабрику сами.

_proxyFactory = new ServiceProxyFactory(c => new ServiceRemotingClientFactoryWrapper(
 // we can use any factory here
 new WcfServiceRemotingClientFactory(callbackClient: c)));

    private class ServiceRemotingClientFactoryWrapper : IServiceRemotingClientFactory
    {
        private readonly IServiceRemotingClientFactory _inner;

        public ServiceRemotingClientFactoryWrapper(IServiceRemotingClientFactory inner)
        {
            _inner = inner;
        }

        public async Task<IServiceRemotingClient> GetClientAsync(Uri serviceUri, ServicePartitionKey partitionKey, TargetReplicaSelector targetReplicaSelector,
            string listenerName, OperationRetrySettings retrySettings, CancellationToken cancellationToken)
        {
            var client = await _inner.GetClientAsync(serviceUri, partitionKey, targetReplicaSelector, listenerName, retrySettings, cancellationToken).ConfigureAwait(false);
            return new ServiceRemotingClientWrapper(client);
        }
    }

    private class ServiceRemotingClientWrapper : IServiceRemotingClient
    {
        private readonly IServiceRemotingClient _inner;

        public ServiceRemotingClientWrapper(IServiceRemotingClient inner)
        {
            _inner = inner;
        }

        public Task<byte[]> RequestResponseAsync(ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
        {
            // use messageHeaders.AddHeader() here
            return _inner.RequestResponseAsync(messageHeaders, requestBody);
        }

        public void SendOneWay(ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
        {
            // use messageHeaders.AddHeader() here
            _inner.SendOneWay(messageHeaders, requestBody);
        }
    }

сервер

Наследовать от ServiceRemotingDispatcher а также ActorServiceRemotingDispatcher изучить заголовки.

class CustomServiceRemotingDispatcher : ServiceRemotingDispatcher
{
    public override async Task<byte[]> RequestResponseAsync(IServiceRemotingRequestContext requestContext, ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
    {
        // read messageHeaders here
        // or alternatively put them in an AsyncLocal<T> scope
        // so they can be accessed down the call chain
        return base.RequestResponseAsync(requestContext, messageHeaders, requestBody);
    }
}

Чтобы использовать этот класс, нам снова нужно переопределить ServiceRemotingProviderAttribute путем непосредственного создания слушателя связи:

class MyService : StatelessService
{
     protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
     {
          yield return new ServiceInstanceListener(context => new WcfServiceRemotingListener(context, new CustomServiceRemotingDispatcher());
     }
}

Я задал тот же вопрос на форуме MSDN несколько недель назад, однако ответа там не получил.

Я изучил исходный код клиентской библиотеки и не нашел способа добавить заголовки. Боюсь, единственный способ - добавить их как часть вызова метода. Это можно сделать, используя классы запросов в качестве параметров метода и используя для них наследование. (например, класс RequestBase с заголовками [Authorization, ClientInfo, ...]). Затем вы должны убедиться, что эти заголовки установлены для каждого запроса, обернув все вызовы или установив его вручную.

Будем весьма благодарны за дальнейшие разъяснения от команды Service Fabric.

Другие вопросы по тегам