Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK committed Aug 29, 2022
1 parent f691e6f commit 7ce7ec3
Showing 1 changed file with 38 additions and 7 deletions.
45 changes: 38 additions & 7 deletions src/Grpc.Net.Client/GrpcChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,18 @@ internal GrpcChannel(Uri address, GrpcChannelOptions channelOptions) : base(addr
Address = address;
LoggerFactory = channelOptions.LoggerFactory ?? channelOptions.ResolveService<ILoggerFactory>(NullLoggerFactory.Instance);
RandomGenerator = channelOptions.ResolveService<IRandomGenerator>(new RandomGenerator());
(HttpHandlerType, ConnectTimeout) = CalculateHandlerContext(channelOptions);

#if SUPPORT_LOAD_BALANCING
InitialReconnectBackoff = channelOptions.InitialReconnectBackoff;
MaxReconnectBackoff = channelOptions.MaxReconnectBackoff;

var resolverFactory = GetResolverFactory(channelOptions);
ResolveCredentials(channelOptions, out _isSecure, out _callCredentials);
(HttpHandlerType, ConnectTimeout) = CalculateHandlerContext(address, _isSecure, channelOptions);

SubchannelTransportFactory = channelOptions.ResolveService<ISubchannelTransportFactory>(new SubChannelTransportFactory(this));

if (!IsHttpOrHttpsAddress() || channelOptions.ServiceConfig?.LoadBalancingConfigs.Count > 0)
if (!IsHttpOrHttpsAddress(Address) || channelOptions.ServiceConfig?.LoadBalancingConfigs.Count > 0)
{
ValidateHttpHandlerSupportsConnectivity();
}
Expand All @@ -149,6 +149,7 @@ internal GrpcChannel(Uri address, GrpcChannelOptions channelOptions) : base(addr
throw new ArgumentException($"Address '{address.OriginalString}' doesn't have a host. Address should include a scheme, host, and optional port. For example, 'https://localhost:5001'.");
}
ResolveCredentials(channelOptions, out _isSecure, out _callCredentials);
(HttpHandlerType, ConnectTimeout) = CalculateHandlerContext(address, _isSecure, channelOptions);
#endif

HttpInvoker = channelOptions.HttpClient ?? CreateInternalHttpInvoker(channelOptions.HttpHandler);
Expand Down Expand Up @@ -213,12 +214,12 @@ private void ResolveCredentials(GrpcChannelOptions channelOptions, out bool isSe
}
}

private bool IsHttpOrHttpsAddress()
private static bool IsHttpOrHttpsAddress(Uri address)
{
return Address.Scheme == Uri.UriSchemeHttps || Address.Scheme == Uri.UriSchemeHttp;
return address.Scheme == Uri.UriSchemeHttps || address.Scheme == Uri.UriSchemeHttp;
}

private static HttpHandlerContext CalculateHandlerContext(GrpcChannelOptions channelOptions)
private static HttpHandlerContext CalculateHandlerContext(Uri address, bool isSecure, GrpcChannelOptions channelOptions)
{
if (channelOptions.HttpHandler == null)
{
Expand Down Expand Up @@ -262,7 +263,10 @@ private static HttpHandlerContext CalculateHandlerContext(GrpcChannelOptions cha
// If a proxy is specified then requests could be sent via an SSL tunnel.
// A CONNECT request is made to the proxy to establish the transport stream and then
// gRPC calls are sent via stream. This feature isn't supported by load balancer.
if (socketsHttpHandler.Proxy != null)
// Proxy can be specified via:
// - SocketsHttpHandler.Proxy. Set via app code.
// - HttpClient.DefaultProxy. Set via environment variables, e.g. HTTPS_PROXY.
if (IsProxied(socketsHttpHandler, address, isSecure))
{
type = HttpHandlerType.Custom;
connectTimeout = null;
Expand All @@ -281,6 +285,33 @@ private static HttpHandlerContext CalculateHandlerContext(GrpcChannelOptions cha
return new HttpHandlerContext(HttpHandlerType.Custom);
}

#if NET5_0_OR_GREATER
private static readonly Uri HttpLoadBalancerTemporaryUri = new Uri("http://loadbalancer.temporary.invalid");
private static readonly Uri HttpsLoadBalancerTemporaryUri = new Uri("https://loadbalancer.temporary.invalid");

private static bool IsProxied(SocketsHttpHandler socketsHttpHandler, Uri address, bool isSecure)
{
// Check standard address directly.
// When load balancing the channel doesn't know the final addresses yet so use temporary address.
Uri resolvedAddress;
if (IsHttpOrHttpsAddress(address))
{
resolvedAddress = address;
}
else if (isSecure)
{
resolvedAddress = HttpsLoadBalancerTemporaryUri;
}
else
{
resolvedAddress = HttpLoadBalancerTemporaryUri;
}

var proxy = socketsHttpHandler.Proxy ?? HttpClient.DefaultProxy;
return proxy.GetProxy(resolvedAddress) != null;
}
#endif

#if SUPPORT_LOAD_BALANCING
private ResolverFactory GetResolverFactory(GrpcChannelOptions options)
{
Expand All @@ -289,7 +320,7 @@ private ResolverFactory GetResolverFactory(GrpcChannelOptions options)
//
// Even with just one address we still want to use the load balancing infrastructure. This enables
// the connectivity APIs on channel like GrpcChannel.State and GrpcChannel.WaitForStateChanged.
if (IsHttpOrHttpsAddress())
if (IsHttpOrHttpsAddress(Address))
{
return new StaticResolverFactory(uri => new[] { new BalancerAddress(Address.Host, Address.Port) });
}
Expand Down

0 comments on commit 7ce7ec3

Please sign in to comment.