如何在使用Azure服务结构的默认客户端时将消息头添加到请求中



我想知道是否可以在不反序列化有效负载的情况下,将自定义消息头注入传出请求以携带额外信息,以完全填充通过messagesinspector提供的wcf等请求的身份验证、验证或关联功能?

更新

使用SDK v2,您现在可以(相对)轻松地修改Reliable Services和Actors的头。请注意,在下面的示例中,为了简洁起见,省略了一些包装器成员。

客户端

我们使用ServiceProxyFactory来创建代理,而不是静态的ServiceProxy。然后我们可以封装IServiceRemotingClientFactoryIServiceRemotingClient并拦截服务调用。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);
        }
    }

服务器

ServiceRemotingDispatcherActorServiceRemotingDispatcher继承以检查标头。

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团队的进一步澄清,我们将不胜感激。

最新更新