Skip to content
Snippets Groups Projects
Commit c831a444 authored by Jan Tattermusch's avatar Jan Tattermusch
Browse files

add ClientBase.WithHost and get rid of HeaderInterceptor

parent b455bcc3
No related branches found
No related tags found
No related merge requests found
...@@ -38,14 +38,6 @@ using Grpc.Core.Utils; ...@@ -38,14 +38,6 @@ using Grpc.Core.Utils;
namespace Grpc.Core namespace Grpc.Core
{ {
/// <summary>
/// Interceptor for call headers.
/// </summary>
/// <remarks>Header interceptor is no longer the recommended way to perform authentication.
/// For header (initial metadata) based auth such as OAuth2 or JWT access token, use <see cref="MetadataCredentials"/>.
/// </remarks>
public delegate void HeaderInterceptor(IMethod method, Metadata metadata);
/// <summary> /// <summary>
/// Generic base class for client-side stubs. /// Generic base class for client-side stubs.
/// </summary> /// </summary>
...@@ -68,6 +60,19 @@ namespace Grpc.Core ...@@ -68,6 +60,19 @@ namespace Grpc.Core
{ {
} }
/// <summary>
/// Creates a new client that sets host field for calls explicitly.
/// gRPC supports multiple "hosts" being served by a single server.
/// By default (if a client was not created by calling this method),
/// host <c>null</c> with the meaning "use default host" is used.
/// </summary>
public T WithHost(string host)
{
GrpcPreconditions.CheckNotNull(host, "host");
var decoratedInvoker = new InterceptingCallInvoker(CallInvoker, hostInterceptor: (h) => host);
return NewInstance(decoratedInvoker);
}
/// <summary> /// <summary>
/// Creates a new instance of client from given <c>CallInvoker</c>. /// Creates a new instance of client from given <c>CallInvoker</c>.
/// </summary> /// </summary>
...@@ -105,53 +110,5 @@ namespace Grpc.Core ...@@ -105,53 +110,5 @@ namespace Grpc.Core
{ {
get { return this.callInvoker; } get { return this.callInvoker; }
} }
/// <summary>
/// Can be used to register a custom header interceptor.
/// The interceptor is invoked each time a new call on this client is started.
/// It is not recommented to use header interceptor to add auth headers to RPC calls.
/// </summary>
/// <seealso cref="HeaderInterceptor"/>
public HeaderInterceptor HeaderInterceptor
{
get;
set;
}
/// <summary>
/// gRPC supports multiple "hosts" being served by a single server.
/// This property can be used to set the target host explicitly.
/// By default, this will be set to <c>null</c> with the meaning
/// "use default host".
/// </summary>
//public string Host
//{
// get;
// set;
//}
/// <summary>
/// Creates a new call to given method.
/// </summary>
/// <param name="method">The method to invoke.</param>
/// <param name="options">The call options.</param>
/// <typeparam name="TRequest">Request message type.</typeparam>
/// <typeparam name="TResponse">Response message type.</typeparam>
/// <returns>The call invocation details.</returns>
//protected CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, CallOptions options)
// where TRequest : class
// where TResponse : class
//{
// var interceptor = HeaderInterceptor;
// if (interceptor != null)
// {
// if (options.Headers == null)
// {
// options = options.WithHeaders(new Metadata());
// }
// interceptor(method, options.Headers);
// }
// return new CallInvocationDetails<TRequest, TResponse>(channel, method, Host, options);
//}
} }
} }
...@@ -75,7 +75,7 @@ namespace Grpc.Core ...@@ -75,7 +75,7 @@ namespace Grpc.Core
/// Invokes a server streaming call asynchronously. /// Invokes a server streaming call asynchronously.
/// In server streaming scenario, client sends on request and server responds with a stream of responses. /// In server streaming scenario, client sends on request and server responds with a stream of responses.
/// </summary> /// </summary>
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{ {
var call = CreateCall(method, host, options); var call = CreateCall(method, host, options);
return Calls.AsyncServerStreamingCall(call, request); return Calls.AsyncServerStreamingCall(call, request);
......
...@@ -131,6 +131,7 @@ ...@@ -131,6 +131,7 @@
<Compile Include="Utils\GrpcPreconditions.cs" /> <Compile Include="Utils\GrpcPreconditions.cs" />
<Compile Include="CallInvoker.cs" /> <Compile Include="CallInvoker.cs" />
<Compile Include="DefaultCallInvoker.cs" /> <Compile Include="DefaultCallInvoker.cs" />
<Compile Include="InterceptingCallInvoker.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Grpc.Core.nuspec" /> <None Include="Grpc.Core.nuspec" />
......
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
/// Decorates an underlying <c>CallInvoker</c> to intercept call invocations.
/// </summary>
internal class InterceptingCallInvoker : CallInvoker
{
readonly CallInvoker callInvoker;
readonly Func<string, string> hostInterceptor;
readonly Func<CallOptions, CallOptions> callOptionsInterceptor;
/// <summary>
/// Initializes a new instance of the <see cref="Grpc.Core.InterceptingCallInvoker"/> class.
/// </summary>
/// <param name="callInvoker">CallInvoker to decorate.</param>
public InterceptingCallInvoker(CallInvoker callInvoker,
Func<string, string> hostInterceptor = null,
Func<CallOptions, CallOptions> callOptionsInterceptor = null)
{
this.callInvoker = GrpcPreconditions.CheckNotNull(callInvoker);
this.hostInterceptor = hostInterceptor;
this.callOptionsInterceptor = callOptionsInterceptor;
}
/// <summary>
/// Intercepts a unary call.
/// </summary>
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.BlockingUnaryCall(method, host, options, request);
}
/// <summary>
/// Invokes a simple remote call asynchronously.
/// </summary>
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncUnaryCall(method, host, options, request);
}
/// <summary>
/// Invokes a server streaming call asynchronously.
/// In server streaming scenario, client sends on request and server responds with a stream of responses.
/// </summary>
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncServerStreamingCall(method, host, options, request);
}
/// <summary>
/// Invokes a client streaming call asynchronously.
/// In client streaming scenario, client sends a stream of requests and server responds with a single response.
/// </summary>
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncClientStreamingCall(method, host, options);
}
/// <summary>
/// Invokes a duplex streaming call asynchronously.
/// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
/// The response stream is completely independent and both side can be sending messages at the same time.
/// </summary>
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncDuplexStreamingCall(method, host, options);
}
private string InterceptHost(string host)
{
// only set host if not already set to support composing interceptors.
if (hostInterceptor == null || host != null)
{
return host;
}
return hostInterceptor(host);
}
private CallOptions InterceptCallOptions(CallOptions options)
{
if (callOptionsInterceptor == null)
{
return options;
}
return callOptionsInterceptor(options);
}
}
}
...@@ -84,7 +84,6 @@ ...@@ -84,7 +84,6 @@
<Compile Include="..\Grpc.Core\Version.cs"> <Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link> <Link>Version.cs</Link>
</Compile> </Compile>
<Compile Include="HeaderInterceptorTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Empty.cs" /> <Compile Include="Empty.cs" />
<Compile Include="Messages.cs" /> <Compile Include="Messages.cs" />
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
"Math.Tests.MathClientServerTest", "Math.Tests.MathClientServerTest",
"Grpc.HealthCheck.Tests.HealthClientServerTest", "Grpc.HealthCheck.Tests.HealthClientServerTest",
"Grpc.HealthCheck.Tests.HealthServiceImplTest", "Grpc.HealthCheck.Tests.HealthServiceImplTest",
"Grpc.IntegrationTesting.HeaderInterceptorTest",
"Grpc.IntegrationTesting.HistogramTest", "Grpc.IntegrationTesting.HistogramTest",
"Grpc.IntegrationTesting.InteropClientServerTest", "Grpc.IntegrationTesting.InteropClientServerTest",
"Grpc.IntegrationTesting.MetadataCredentialsTest", "Grpc.IntegrationTesting.MetadataCredentialsTest",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment