mirror of https://github.com/grpc/grpc-java.git
core,netty,okhttp: detect proxy via ProxySelector (#3021)
This lets us specify the proxy using `-Dhttps.proxyHost=host -Dhttps.proxyPort=port` along with auth info like username and password.
This commit is contained in:
parent
b9f6590084
commit
7df9ae9753
|
|
@ -23,6 +23,7 @@ import io.grpc.internal.AbstractManagedChannelImplBuilder;
|
|||
import io.grpc.internal.ClientTransportFactory;
|
||||
import io.grpc.internal.ConnectionClientTransport;
|
||||
import io.grpc.internal.GrpcUtil;
|
||||
import io.grpc.internal.ProxyParameters;
|
||||
import io.grpc.internal.SharedResourceHolder;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
|
@ -128,7 +129,7 @@ public final class InProcessChannelBuilder extends
|
|||
|
||||
@Override
|
||||
public ConnectionClientTransport newClientTransport(
|
||||
SocketAddress addr, String authority, String userAgent) {
|
||||
SocketAddress addr, String authority, String userAgent, ProxyParameters proxy) {
|
||||
if (closed) {
|
||||
throw new IllegalStateException("The transport factory is closed.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,8 @@ public abstract class AbstractManagedChannelImplBuilder
|
|||
String authorityOverride;
|
||||
|
||||
|
||||
private ProxyDetector proxyDetector = ProxyDetector.DEFAULT_INSTANCE;
|
||||
|
||||
LoadBalancer.Factory loadBalancerFactory = DEFAULT_LOAD_BALANCER_FACTORY;
|
||||
|
||||
boolean fullStreamDecompression;
|
||||
|
|
@ -335,7 +337,8 @@ public abstract class AbstractManagedChannelImplBuilder
|
|||
new ExponentialBackoffPolicy.Provider(),
|
||||
SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR),
|
||||
GrpcUtil.STOPWATCH_SUPPLIER,
|
||||
getEffectiveInterceptors());
|
||||
getEffectiveInterceptors(),
|
||||
proxyDetector);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
|
|||
|
|
@ -42,9 +42,10 @@ final class CallCredentialsApplyingTransportFactory implements ClientTransportFa
|
|||
|
||||
@Override
|
||||
public ConnectionClientTransport newClientTransport(
|
||||
SocketAddress serverAddress, String authority, @Nullable String userAgent) {
|
||||
SocketAddress serverAddress, String authority, @Nullable String userAgent,
|
||||
@Nullable ProxyParameters proxy) {
|
||||
return new CallCredentialsApplyingTransport(
|
||||
delegate.newClientTransport(serverAddress, authority, userAgent), authority);
|
||||
delegate.newClientTransport(serverAddress, authority, userAgent, proxy), authority);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@ public interface ClientTransportFactory extends Closeable {
|
|||
*
|
||||
* @param serverAddress the address that the transport is connected to
|
||||
* @param authority the HTTP/2 authority of the server
|
||||
* @param proxy the proxy that should be used to connect to serverAddress
|
||||
*/
|
||||
ConnectionClientTransport newClientTransport(SocketAddress serverAddress, String authority,
|
||||
@Nullable String userAgent);
|
||||
@Nullable String userAgent, @Nullable ProxyParameters proxy);
|
||||
|
||||
/**
|
||||
* Returns an executor for scheduling provided by the transport. The service should be configured
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ final class DnsNameResolver extends NameResolver {
|
|||
private final int port;
|
||||
private final Resource<ScheduledExecutorService> timerServiceResource;
|
||||
private final Resource<ExecutorService> executorResource;
|
||||
private final ProxyDetector proxyDetector;
|
||||
@GuardedBy("this")
|
||||
private boolean shutdown;
|
||||
@GuardedBy("this")
|
||||
|
|
@ -84,7 +85,8 @@ final class DnsNameResolver extends NameResolver {
|
|||
|
||||
DnsNameResolver(@Nullable String nsAuthority, String name, Attributes params,
|
||||
Resource<ScheduledExecutorService> timerServiceResource,
|
||||
Resource<ExecutorService> executorResource) {
|
||||
Resource<ExecutorService> executorResource,
|
||||
ProxyDetector proxyDetector) {
|
||||
// TODO: if a DNS server is provided as nsAuthority, use it.
|
||||
// https://www.captechconsulting.com/blogs/accessing-the-dusty-corners-of-dns-with-java
|
||||
this.timerServiceResource = timerServiceResource;
|
||||
|
|
@ -106,6 +108,7 @@ final class DnsNameResolver extends NameResolver {
|
|||
} else {
|
||||
port = nameUri.getPort();
|
||||
}
|
||||
this.proxyDetector = proxyDetector;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -145,9 +148,10 @@ final class DnsNameResolver extends NameResolver {
|
|||
resolving = true;
|
||||
}
|
||||
try {
|
||||
if (System.getenv("GRPC_PROXY_EXP") != null) {
|
||||
EquivalentAddressGroup server =
|
||||
new EquivalentAddressGroup(InetSocketAddress.createUnresolved(host, port));
|
||||
InetSocketAddress destination = InetSocketAddress.createUnresolved(host, port);
|
||||
ProxyParameters proxy = proxyDetector.proxyFor(destination);
|
||||
if (proxy != null) {
|
||||
EquivalentAddressGroup server = new EquivalentAddressGroup(destination);
|
||||
savedListener.onAddresses(Collections.singletonList(server), Attributes.EMPTY);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public final class DnsNameResolverProvider extends NameResolverProvider {
|
|||
"the path component (%s) of the target (%s) must start with '/'", targetPath, targetUri);
|
||||
String name = targetPath.substring(1);
|
||||
return new DnsNameResolver(targetUri.getAuthority(), name, params, GrpcUtil.TIMER_SERVICE,
|
||||
GrpcUtil.SHARED_CHANNEL_EXECUTOR);
|
||||
GrpcUtil.SHARED_CHANNEL_EXECUTOR, ProxyDetector.DEFAULT_INSTANCE);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,10 @@ import io.grpc.internal.SharedResourceHolder.Resource;
|
|||
import io.grpc.internal.StreamListener.MessageProducer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
|
|
@ -534,6 +536,25 @@ public final class GrpcUtil {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the host via {@link InetSocketAddress#getHostString} if it is possible,
|
||||
* i.e. in jdk >= 7.
|
||||
* Otherwise, return it via {@link InetSocketAddress#getHostName} which may incur a DNS lookup.
|
||||
*/
|
||||
public static String getHost(InetSocketAddress addr) {
|
||||
try {
|
||||
Method getHostStringMethod = InetSocketAddress.class.getMethod("getHostString");
|
||||
return (String) getHostStringMethod.invoke(addr);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// noop
|
||||
} catch (IllegalAccessException e) {
|
||||
// noop
|
||||
} catch (InvocationTargetException e) {
|
||||
// noop
|
||||
}
|
||||
return addr.getHostName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshals a nanoseconds representation of the timeout to and from a string representation,
|
||||
* consisting of an ASCII decimal representation of a number with at most 8 digits, followed by a
|
||||
|
|
|
|||
|
|
@ -137,13 +137,17 @@ final class InternalSubchannel implements WithLogId {
|
|||
@GuardedBy("lock")
|
||||
private ConnectivityStateInfo state = ConnectivityStateInfo.forNonError(IDLE);
|
||||
|
||||
private final ProxyDetector proxyDetector;
|
||||
|
||||
@GuardedBy("lock")
|
||||
private Status shutdownReason;
|
||||
|
||||
|
||||
InternalSubchannel(EquivalentAddressGroup addressGroup, String authority, String userAgent,
|
||||
BackoffPolicy.Provider backoffPolicyProvider,
|
||||
ClientTransportFactory transportFactory, ScheduledExecutorService scheduledExecutor,
|
||||
Supplier<Stopwatch> stopwatchSupplier, ChannelExecutor channelExecutor, Callback callback) {
|
||||
Supplier<Stopwatch> stopwatchSupplier, ChannelExecutor channelExecutor, Callback callback,
|
||||
ProxyDetector proxyDetector) {
|
||||
this.addressGroup = Preconditions.checkNotNull(addressGroup, "addressGroup");
|
||||
this.authority = authority;
|
||||
this.userAgent = userAgent;
|
||||
|
|
@ -153,6 +157,7 @@ final class InternalSubchannel implements WithLogId {
|
|||
this.connectingTimer = stopwatchSupplier.get();
|
||||
this.channelExecutor = channelExecutor;
|
||||
this.callback = callback;
|
||||
this.proxyDetector = proxyDetector;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -194,8 +199,9 @@ final class InternalSubchannel implements WithLogId {
|
|||
List<SocketAddress> addrs = addressGroup.getAddresses();
|
||||
final SocketAddress address = addrs.get(addressIndex);
|
||||
|
||||
ProxyParameters proxy = proxyDetector.proxyFor(address);
|
||||
ConnectionClientTransport transport =
|
||||
transportFactory.newClientTransport(address, authority, userAgent);
|
||||
transportFactory.newClientTransport(address, authority, userAgent, proxy);
|
||||
if (log.isLoggable(Level.FINE)) {
|
||||
log.log(Level.FINE, "[{0}] Created {1} for {2}",
|
||||
new Object[] {logId, transport.getLogId(), address});
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ public final class ManagedChannelImpl extends ManagedChannel implements WithLogI
|
|||
// Only null after channel is terminated. Must be assigned from the channelExecutor.
|
||||
private NameResolver nameResolver;
|
||||
|
||||
private final ProxyDetector proxyDetector;
|
||||
|
||||
// null when channel is in idle mode. Must be assigned from channelExecutor.
|
||||
@Nullable
|
||||
private LbHelperImpl lbHelper;
|
||||
|
|
@ -386,7 +388,8 @@ public final class ManagedChannelImpl extends ManagedChannel implements WithLogI
|
|||
BackoffPolicy.Provider backoffPolicyProvider,
|
||||
ObjectPool<? extends Executor> oobExecutorPool,
|
||||
Supplier<Stopwatch> stopwatchSupplier,
|
||||
List<ClientInterceptor> interceptors) {
|
||||
List<ClientInterceptor> interceptors,
|
||||
ProxyDetector proxyDetector) {
|
||||
this.target = checkNotNull(builder.target, "target");
|
||||
this.nameResolverFactory = builder.getNameResolverFactory();
|
||||
this.nameResolverParams = checkNotNull(builder.getNameResolverParams(), "nameResolverParams");
|
||||
|
|
@ -416,6 +419,7 @@ public final class ManagedChannelImpl extends ManagedChannel implements WithLogI
|
|||
this.decompressorRegistry = checkNotNull(builder.decompressorRegistry, "decompressorRegistry");
|
||||
this.compressorRegistry = checkNotNull(builder.compressorRegistry, "compressorRegistry");
|
||||
this.userAgent = builder.userAgent;
|
||||
this.proxyDetector = proxyDetector;
|
||||
|
||||
phantom = new ManagedChannelReference(this);
|
||||
logger.log(Level.FINE, "[{0}] Created with target {1}", new Object[] {getLogId(), target});
|
||||
|
|
@ -674,7 +678,8 @@ public final class ManagedChannelImpl extends ManagedChannel implements WithLogI
|
|||
void onNotInUse(InternalSubchannel is) {
|
||||
inUseStateAggregator.updateObjectInUse(is, false);
|
||||
}
|
||||
});
|
||||
},
|
||||
proxyDetector);
|
||||
subchannel.subchannel = internalSubchannel;
|
||||
logger.log(Level.FINE, "[{0}] {1} created for {2}",
|
||||
new Object[] {getLogId(), internalSubchannel.getLogId(), addressGroup});
|
||||
|
|
@ -754,7 +759,8 @@ public final class ManagedChannelImpl extends ManagedChannel implements WithLogI
|
|||
void onStateChange(InternalSubchannel is, ConnectivityStateInfo newState) {
|
||||
oobChannel.handleSubchannelStateChange(newState);
|
||||
}
|
||||
});
|
||||
},
|
||||
proxyDetector);
|
||||
oobChannel.setSubchannel(internalSubchannel);
|
||||
runSerialized(new Runnable() {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2017, gRPC Authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.internal;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A utility class to detect which proxy, if any, should be used for a given
|
||||
* {@link java.net.SocketAddress}.
|
||||
*/
|
||||
public interface ProxyDetector {
|
||||
ProxyDetector DEFAULT_INSTANCE = new ProxyDetectorImpl();
|
||||
|
||||
/** A proxy detector that always claims no proxy is needed, for unit test convenience. */
|
||||
ProxyDetector NOOP_INSTANCE = new ProxyDetector() {
|
||||
@Nullable
|
||||
@Override
|
||||
public ProxyParameters proxyFor(SocketAddress targetServerAddress) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a target address, returns which proxy address should be used. If no proxy should be
|
||||
* used, then return value will be null.
|
||||
*/
|
||||
@Nullable
|
||||
ProxyParameters proxyFor(SocketAddress targetServerAddress);
|
||||
}
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright 2017, gRPC Authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Supplier;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A utility class that detects proxies using {@link ProxySelector} and detects authentication
|
||||
* credentials using {@link Authenticator}.
|
||||
*
|
||||
*/
|
||||
class ProxyDetectorImpl implements ProxyDetector {
|
||||
private static final Logger log = Logger.getLogger(ProxyDetectorImpl.class.getName());
|
||||
private static final AuthenticationProvider DEFAULT_AUTHENTICATOR = new AuthenticationProvider() {
|
||||
@Override
|
||||
public PasswordAuthentication requestPasswordAuthentication(
|
||||
String host, InetAddress addr, int port, String protocol, String prompt, String scheme) {
|
||||
URL url = null;
|
||||
try {
|
||||
url = new URL(protocol, host, "");
|
||||
} catch (MalformedURLException e) {
|
||||
// let url be null
|
||||
log.log(
|
||||
Level.WARNING,
|
||||
String.format("failed to create URL for Authenticator: %s %s", protocol, host));
|
||||
}
|
||||
// TODO(spencerfang): consider using java.security.AccessController here
|
||||
return Authenticator.requestPasswordAuthentication(
|
||||
host, addr, port, protocol, prompt, scheme, url, Authenticator.RequestorType.PROXY);
|
||||
}
|
||||
};
|
||||
private static final Supplier<ProxySelector> DEFAULT_PROXY_SELECTOR =
|
||||
new Supplier<ProxySelector>() {
|
||||
@Override
|
||||
public ProxySelector get() {
|
||||
// TODO(spencerfang): consider using java.security.AccessController here
|
||||
return ProxySelector.getDefault();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated Use the standard Java proxy configuration instead with flags such as:
|
||||
* -Dhttps.proxyHost=HOST -Dhttps.proxyPort=PORT
|
||||
*/
|
||||
@Deprecated
|
||||
private static final String GRPC_PROXY_ENV_VAR = "GRPC_PROXY_EXP";
|
||||
// Do not hard code a ProxySelector because the global default ProxySelector can change
|
||||
private final Supplier<ProxySelector> proxySelector;
|
||||
private final AuthenticationProvider authenticationProvider;
|
||||
private final ProxyParameters override;
|
||||
|
||||
// We want an HTTPS proxy, which operates on the entire data stream (See IETF rfc2817).
|
||||
static final String PROXY_SCHEME = "https";
|
||||
|
||||
/**
|
||||
* A proxy selector that uses the global {@link ProxySelector#getDefault()} and
|
||||
* {@link ProxyDetectorImpl.AuthenticationProvider} to detect proxy parameters.
|
||||
*/
|
||||
public ProxyDetectorImpl() {
|
||||
this(DEFAULT_PROXY_SELECTOR, DEFAULT_AUTHENTICATOR, System.getenv(GRPC_PROXY_ENV_VAR));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ProxyDetectorImpl(
|
||||
Supplier<ProxySelector> proxySelector,
|
||||
AuthenticationProvider authenticationProvider,
|
||||
@Nullable String proxyEnvString) {
|
||||
this.proxySelector = checkNotNull(proxySelector);
|
||||
this.authenticationProvider = checkNotNull(authenticationProvider);
|
||||
if (proxyEnvString != null) {
|
||||
override = new ProxyParameters(overrideProxy(proxyEnvString), null, null);
|
||||
} else {
|
||||
override = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ProxyParameters proxyFor(SocketAddress targetServerAddress) {
|
||||
if (override != null) {
|
||||
return override;
|
||||
}
|
||||
if (!(targetServerAddress instanceof InetSocketAddress)) {
|
||||
return null;
|
||||
}
|
||||
return detectProxy((InetSocketAddress) targetServerAddress);
|
||||
}
|
||||
|
||||
private ProxyParameters detectProxy(InetSocketAddress targetAddr) {
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(
|
||||
PROXY_SCHEME,
|
||||
null, /* userInfo */
|
||||
targetAddr.getHostName(),
|
||||
targetAddr.getPort(),
|
||||
null, /* path */
|
||||
null, /* query */
|
||||
null /* fragment */);
|
||||
} catch (final URISyntaxException e) {
|
||||
log.log(
|
||||
Level.WARNING,
|
||||
"Failed to construct URI for proxy lookup, proceeding without proxy",
|
||||
e);
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Proxy> proxies = proxySelector.get().select(uri);
|
||||
if (proxies.size() > 1) {
|
||||
log.warning("More than 1 proxy detected, gRPC will select the first one");
|
||||
}
|
||||
Proxy proxy = proxies.get(0);
|
||||
|
||||
if (proxy.type() == Proxy.Type.DIRECT) {
|
||||
return null;
|
||||
}
|
||||
InetSocketAddress proxyAddr = (InetSocketAddress) proxy.address();
|
||||
// The prompt string should be the realm as returned by the server.
|
||||
// We don't have it because we are avoiding the full handshake.
|
||||
String promptString = "";
|
||||
PasswordAuthentication auth = authenticationProvider.requestPasswordAuthentication(
|
||||
GrpcUtil.getHost(proxyAddr),
|
||||
proxyAddr.getAddress(),
|
||||
proxyAddr.getPort(),
|
||||
PROXY_SCHEME,
|
||||
promptString,
|
||||
null);
|
||||
|
||||
if (auth == null) {
|
||||
return new ProxyParameters(proxyAddr, null, null);
|
||||
}
|
||||
|
||||
// TODO(spencerfang): users of ProxyParameters should clear the password when done
|
||||
return new ProxyParameters(proxyAddr, auth.getUserName(), new String(auth.getPassword()));
|
||||
}
|
||||
|
||||
/**
|
||||
* GRPC_PROXY_EXP is deprecated but let's maintain compatibility for now.
|
||||
*/
|
||||
private static InetSocketAddress overrideProxy(String proxyHostPort) {
|
||||
if (proxyHostPort == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] parts = proxyHostPort.split(":", 2);
|
||||
int port = 80;
|
||||
if (parts.length > 1) {
|
||||
port = Integer.parseInt(parts[1]);
|
||||
}
|
||||
log.warning(
|
||||
"Detected GRPC_PROXY_EXP and will honor it, but this feature will "
|
||||
+ "be removed in a future release. Use the JVM flags "
|
||||
+ "\"-Dhttps.proxyHost=HOST -Dhttps.proxyPort=PORT\" to set the https proxy for "
|
||||
+ "this JVM.");
|
||||
return new InetSocketAddress(parts[0], port);
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface makes unit testing easier by avoiding direct calls to static methods.
|
||||
*/
|
||||
interface AuthenticationProvider {
|
||||
PasswordAuthentication requestPasswordAuthentication(
|
||||
String host,
|
||||
InetAddress addr,
|
||||
int port,
|
||||
String protocol,
|
||||
String prompt,
|
||||
String scheme);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2017, gRPC Authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.internal;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.net.InetSocketAddress;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Used to express the result of a proxy lookup.
|
||||
*/
|
||||
public final class ProxyParameters {
|
||||
public final InetSocketAddress proxyAddress;
|
||||
@Nullable public final String username;
|
||||
@Nullable public final String password;
|
||||
|
||||
ProxyParameters(
|
||||
InetSocketAddress proxyAddress,
|
||||
@Nullable String username,
|
||||
@Nullable String password) {
|
||||
this.proxyAddress = Preconditions.checkNotNull(proxyAddress);
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof ProxyParameters)) {
|
||||
return false;
|
||||
}
|
||||
ProxyParameters that = (ProxyParameters) o;
|
||||
return Objects.equal(proxyAddress, that.proxyAddress)
|
||||
&& Objects.equal(username, that.username)
|
||||
&& Objects.equal(password, that.password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(proxyAddress, username, password);
|
||||
}
|
||||
}
|
||||
|
|
@ -75,6 +75,7 @@ public class CallCredentialsApplyingTest {
|
|||
|
||||
private static final String AUTHORITY = "testauthority";
|
||||
private static final String USER_AGENT = "testuseragent";
|
||||
private static final ProxyParameters NO_PROXY = null;
|
||||
private static final Attributes.Key<String> ATTR_KEY = Attributes.Key.of("somekey");
|
||||
private static final String ATTR_VALUE = "somevalue";
|
||||
private static final MethodDescriptor<String, Integer> method =
|
||||
|
|
@ -99,16 +100,16 @@ public class CallCredentialsApplyingTest {
|
|||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
origHeaders.put(ORIG_HEADER_KEY, ORIG_HEADER_VALUE);
|
||||
when(mockTransportFactory.newClientTransport(address, AUTHORITY, USER_AGENT))
|
||||
when(mockTransportFactory.newClientTransport(address, AUTHORITY, USER_AGENT, NO_PROXY))
|
||||
.thenReturn(mockTransport);
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
.thenReturn(mockStream);
|
||||
ClientTransportFactory transportFactory = new CallCredentialsApplyingTransportFactory(
|
||||
mockTransportFactory, mockExecutor);
|
||||
transport = (ForwardingConnectionClientTransport) transportFactory.newClientTransport(
|
||||
address, AUTHORITY, USER_AGENT);
|
||||
address, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
callOptions = CallOptions.DEFAULT.withCallCredentials(mockCreds);
|
||||
verify(mockTransportFactory).newClientTransport(address, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(address, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertSame(mockTransport, transport.delegate());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,15 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
|
@ -37,6 +41,7 @@ import io.grpc.internal.DnsNameResolver.ResolutionResults;
|
|||
import io.grpc.internal.SharedResourceHolder.Resource;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -107,13 +112,22 @@ public class DnsNameResolverTest {
|
|||
private ArgumentCaptor<Status> statusCaptor;
|
||||
|
||||
private DnsNameResolver newResolver(String name, int port) {
|
||||
return newResolver(name, port, mockResolver, ProxyDetector.NOOP_INSTANCE);
|
||||
}
|
||||
|
||||
private DnsNameResolver newResolver(
|
||||
String name,
|
||||
int port,
|
||||
DelegateResolver delegateResolver,
|
||||
ProxyDetector proxyDetector) {
|
||||
DnsNameResolver dnsResolver = new DnsNameResolver(
|
||||
null,
|
||||
name,
|
||||
Attributes.newBuilder().set(NameResolver.Factory.PARAMS_DEFAULT_PORT, port).build(),
|
||||
fakeTimerServiceResource,
|
||||
fakeExecutorResource);
|
||||
dnsResolver.setDelegateResolver(mockResolver);
|
||||
fakeExecutorResource,
|
||||
proxyDetector);
|
||||
dnsResolver.setDelegateResolver(delegateResolver);
|
||||
return dnsResolver;
|
||||
}
|
||||
|
||||
|
|
@ -335,6 +349,32 @@ public class DnsNameResolverTest {
|
|||
assertThat(results.txtRecords).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doNotResolveWhenProxyDetected() throws Exception {
|
||||
final String name = "foo.googleapis.com";
|
||||
final int port = 81;
|
||||
ProxyDetector alwaysDetectProxy = mock(ProxyDetector.class);
|
||||
ProxyParameters proxyParameters = new ProxyParameters(
|
||||
InetSocketAddress.createUnresolved("proxy.example.com", 1000),
|
||||
"username",
|
||||
"password");
|
||||
when(alwaysDetectProxy.proxyFor(any(SocketAddress.class)))
|
||||
.thenReturn(proxyParameters);
|
||||
DelegateResolver unusedResolver = mock(DelegateResolver.class);
|
||||
DnsNameResolver resolver = newResolver(name, port, unusedResolver, alwaysDetectProxy);
|
||||
resolver.start(mockListener);
|
||||
assertEquals(1, fakeExecutor.runDueTasks());
|
||||
verify(unusedResolver, never()).resolve(any(String.class));
|
||||
|
||||
verify(mockListener).onAddresses(resultCaptor.capture(), any(Attributes.class));
|
||||
List<EquivalentAddressGroup> result = resultCaptor.getValue();
|
||||
assertThat(result).hasSize(1);
|
||||
EquivalentAddressGroup eag = result.get(0);
|
||||
assertThat(eag.getAddresses()).hasSize(1);
|
||||
SocketAddress socketAddress = eag.getAddresses().get(0);
|
||||
assertTrue(((InetSocketAddress) socketAddress).isUnresolved());
|
||||
}
|
||||
|
||||
private void testInvalidUri(URI uri) {
|
||||
try {
|
||||
provider.newNameResolver(uri, NAME_RESOLVER_PARAMS);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import static org.junit.Assert.assertNull;
|
|||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.same;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
|
@ -36,15 +37,18 @@ import static org.mockito.Mockito.verify;
|
|||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.grpc.ConnectivityState;
|
||||
import io.grpc.ConnectivityStateInfo;
|
||||
import io.grpc.EquivalentAddressGroup;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.internal.TestUtils.MockClientTransportInfo;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.annotation.Nullable;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
|
@ -61,6 +65,7 @@ public class InternalSubchannelTest {
|
|||
|
||||
private static final String AUTHORITY = "fakeauthority";
|
||||
private static final String USER_AGENT = "mosaic";
|
||||
private static final ProxyParameters NO_PROXY = null;
|
||||
private static final ConnectivityStateInfo UNAVAILABLE_STATE =
|
||||
ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE);
|
||||
private static final ConnectivityStateInfo RESOURCE_EXHAUSTED_STATE =
|
||||
|
|
@ -145,7 +150,7 @@ public class InternalSubchannelTest {
|
|||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
verify(mockTransportFactory, times(++transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// Fail this one. Because there is only one address to try, enter TRANSIENT_FAILURE.
|
||||
assertNoCallbackInvoke();
|
||||
|
|
@ -161,7 +166,7 @@ public class InternalSubchannelTest {
|
|||
fakeClock.forwardNanos(9);
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
verify(mockTransportFactory, times(transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertEquals(TRANSIENT_FAILURE, internalSubchannel.getState());
|
||||
|
||||
assertNoCallbackInvoke();
|
||||
|
|
@ -169,7 +174,7 @@ public class InternalSubchannelTest {
|
|||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
verify(mockTransportFactory, times(++transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
// Fail this one too
|
||||
assertNoCallbackInvoke();
|
||||
// Here we use a different status from the first failure, and verify that it's passed to
|
||||
|
|
@ -186,7 +191,7 @@ public class InternalSubchannelTest {
|
|||
fakeClock.forwardNanos(99);
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
verify(mockTransportFactory, times(transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertEquals(TRANSIENT_FAILURE, internalSubchannel.getState());
|
||||
assertNoCallbackInvoke();
|
||||
fakeClock.forwardNanos(1);
|
||||
|
|
@ -194,7 +199,7 @@ public class InternalSubchannelTest {
|
|||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
verify(mockTransportFactory, times(++transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
// Let this one succeed, will enter READY state.
|
||||
assertNoCallbackInvoke();
|
||||
transports.peek().listener.transportReady();
|
||||
|
|
@ -214,7 +219,7 @@ public class InternalSubchannelTest {
|
|||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockBackoffPolicyProvider, times(backoffReset)).get();
|
||||
verify(mockTransportFactory, times(++transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// Final checks for consultations on back-off policies
|
||||
verify(mockBackoffPolicy1, times(backoff1Consulted)).nextBackoffNanos();
|
||||
|
|
@ -240,7 +245,7 @@ public class InternalSubchannelTest {
|
|||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
verify(mockTransportFactory, times(++transportsAddr1))
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// Let this one fail without success
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
|
|
@ -252,7 +257,7 @@ public class InternalSubchannelTest {
|
|||
// Second attempt will start immediately. Still no back-off policy.
|
||||
verify(mockBackoffPolicyProvider, times(backoffReset)).get();
|
||||
verify(mockTransportFactory, times(++transportsAddr2))
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
// Fail this one too
|
||||
assertNoCallbackInvoke();
|
||||
|
|
@ -272,14 +277,14 @@ public class InternalSubchannelTest {
|
|||
// Third attempt is the first address, thus controlled by the first back-off interval.
|
||||
fakeClock.forwardNanos(9);
|
||||
verify(mockTransportFactory, times(transportsAddr1))
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertEquals(TRANSIENT_FAILURE, internalSubchannel.getState());
|
||||
assertNoCallbackInvoke();
|
||||
fakeClock.forwardNanos(1);
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
verify(mockTransportFactory, times(++transportsAddr1))
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
// Fail this one too
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
|
|
@ -289,7 +294,7 @@ public class InternalSubchannelTest {
|
|||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
verify(mockBackoffPolicyProvider, times(backoffReset)).get();
|
||||
verify(mockTransportFactory, times(++transportsAddr2))
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
// Fail this one too
|
||||
assertNoCallbackInvoke();
|
||||
transports.poll().listener.transportShutdown(Status.RESOURCE_EXHAUSTED);
|
||||
|
|
@ -304,14 +309,14 @@ public class InternalSubchannelTest {
|
|||
assertEquals(TRANSIENT_FAILURE, internalSubchannel.getState());
|
||||
fakeClock.forwardNanos(99);
|
||||
verify(mockTransportFactory, times(transportsAddr1))
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertEquals(TRANSIENT_FAILURE, internalSubchannel.getState());
|
||||
assertNoCallbackInvoke();
|
||||
fakeClock.forwardNanos(1);
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
verify(mockTransportFactory, times(++transportsAddr1))
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
// Let it through
|
||||
assertNoCallbackInvoke();
|
||||
transports.peek().listener.transportReady();
|
||||
|
|
@ -332,7 +337,7 @@ public class InternalSubchannelTest {
|
|||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockBackoffPolicyProvider, times(backoffReset)).get();
|
||||
verify(mockTransportFactory, times(++transportsAddr1))
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
// Fail the transport
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
|
|
@ -340,7 +345,7 @@ public class InternalSubchannelTest {
|
|||
// Second attempt will start immediately. Still no new back-off policy.
|
||||
verify(mockBackoffPolicyProvider, times(backoffReset)).get();
|
||||
verify(mockTransportFactory, times(++transportsAddr2))
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
// Fail this one too
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
|
|
@ -354,14 +359,14 @@ public class InternalSubchannelTest {
|
|||
// Third attempt is the first address, thus controlled by the first back-off interval.
|
||||
fakeClock.forwardNanos(9);
|
||||
verify(mockTransportFactory, times(transportsAddr1))
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertEquals(TRANSIENT_FAILURE, internalSubchannel.getState());
|
||||
assertNoCallbackInvoke();
|
||||
fakeClock.forwardNanos(1);
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
verify(mockTransportFactory, times(++transportsAddr1))
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// Final checks on invocations on back-off policies
|
||||
verify(mockBackoffPolicy1, times(backoff1Consulted)).nextBackoffNanos();
|
||||
|
|
@ -379,12 +384,12 @@ public class InternalSubchannelTest {
|
|||
// First address fails
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory).newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
|
||||
// Second address connects
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.peek().listener.transportReady();
|
||||
assertExactCallbackInvokes("onStateChange:READY");
|
||||
assertEquals(READY, internalSubchannel.getState());
|
||||
|
|
@ -402,9 +407,10 @@ public class InternalSubchannelTest {
|
|||
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertEquals(0, fakeClock.numPendingTasks());
|
||||
verify(mockTransportFactory, times(2)).newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory, times(2))
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
verify(mockTransportFactory).newClientTransport(addr3, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr3, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
verifyNoMoreInteractions(mockTransportFactory);
|
||||
|
||||
|
|
@ -421,12 +427,12 @@ public class InternalSubchannelTest {
|
|||
// First address fails
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory).newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
|
||||
// Second address connecting
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertNoCallbackInvoke();
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
|
||||
|
|
@ -445,9 +451,10 @@ public class InternalSubchannelTest {
|
|||
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertEquals(0, fakeClock.numPendingTasks());
|
||||
verify(mockTransportFactory, times(2)).newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory, times(2))
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
verify(mockTransportFactory).newClientTransport(addr3, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr3, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
verifyNoMoreInteractions(mockTransportFactory);
|
||||
|
||||
|
|
@ -462,8 +469,10 @@ public class InternalSubchannelTest {
|
|||
internalSubchannel.updateAddresses(new EquivalentAddressGroup(addr2));
|
||||
|
||||
// Nothing happened on address update
|
||||
verify(mockTransportFactory, never()).newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory, never()).newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory, never())
|
||||
.newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
verify(mockTransportFactory, never())
|
||||
.newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
verifyNoMoreInteractions(mockTransportFactory);
|
||||
assertNoCallbackInvoke();
|
||||
assertEquals(IDLE, internalSubchannel.getState());
|
||||
|
|
@ -471,7 +480,7 @@ public class InternalSubchannelTest {
|
|||
// But new address chosen when connecting
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// And no other addresses attempted
|
||||
assertEquals(0, fakeClock.numPendingTasks());
|
||||
|
|
@ -494,12 +503,12 @@ public class InternalSubchannelTest {
|
|||
// First address fails
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory).newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
|
||||
// Second address connects
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.peek().listener.transportReady();
|
||||
assertExactCallbackInvokes("onStateChange:READY");
|
||||
assertEquals(READY, internalSubchannel.getState());
|
||||
|
|
@ -517,9 +526,9 @@ public class InternalSubchannelTest {
|
|||
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertEquals(0, fakeClock.numPendingTasks());
|
||||
verify(mockTransportFactory).newClientTransport(addr3, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr3, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
verify(mockTransportFactory).newClientTransport(addr4, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr4, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
verifyNoMoreInteractions(mockTransportFactory);
|
||||
|
||||
|
|
@ -537,12 +546,12 @@ public class InternalSubchannelTest {
|
|||
// First address fails
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory).newClientTransport(addr1, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr1, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
|
||||
// Second address connecting
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr2, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertNoCallbackInvoke();
|
||||
assertEquals(CONNECTING, internalSubchannel.getState());
|
||||
|
||||
|
|
@ -558,9 +567,9 @@ public class InternalSubchannelTest {
|
|||
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertEquals(0, fakeClock.numPendingTasks());
|
||||
verify(mockTransportFactory).newClientTransport(addr3, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr3, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
verify(mockTransportFactory).newClientTransport(addr4, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr4, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
verifyNoMoreInteractions(mockTransportFactory);
|
||||
|
||||
|
|
@ -577,13 +586,13 @@ public class InternalSubchannelTest {
|
|||
|
||||
// Won't connect until requested
|
||||
verify(mockTransportFactory, times(transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// First attempt
|
||||
internalSubchannel.obtainActiveTransport();
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory, times(++transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// Fail this one
|
||||
transports.poll().listener.transportShutdown(Status.UNAVAILABLE);
|
||||
|
|
@ -593,7 +602,7 @@ public class InternalSubchannelTest {
|
|||
fakeClock.forwardNanos(10);
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory, times(++transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// Make this one proceed
|
||||
transports.peek().listener.transportReady();
|
||||
|
|
@ -610,7 +619,7 @@ public class InternalSubchannelTest {
|
|||
internalSubchannel.obtainActiveTransport();
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory, times(++transportsCreated))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -640,7 +649,7 @@ public class InternalSubchannelTest {
|
|||
// First transport is created immediately
|
||||
internalSubchannel.obtainActiveTransport();
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
verify(mockTransportFactory).newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory).newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
|
||||
// Fail this one
|
||||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
|
|
@ -740,7 +749,8 @@ public class InternalSubchannelTest {
|
|||
assertExactCallbackInvokes("onStateChange:SHUTDOWN", "onTerminated");
|
||||
assertEquals(SHUTDOWN, internalSubchannel.getState());
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
verify(mockTransportFactory, times(0)).newClientTransport(addr, AUTHORITY, USER_AGENT);
|
||||
verify(mockTransportFactory, times(0))
|
||||
.newClientTransport(addr, AUTHORITY, USER_AGENT, NO_PROXY);
|
||||
assertNoCallbackInvoke();
|
||||
assertEquals(SHUTDOWN, internalSubchannel.getState());
|
||||
}
|
||||
|
|
@ -848,11 +858,43 @@ public class InternalSubchannelTest {
|
|||
assertEquals(3, runnableInvokes.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyTest() {
|
||||
final SocketAddress addr1 = mock(SocketAddress.class);
|
||||
final ProxyParameters proxy = new ProxyParameters(
|
||||
InetSocketAddress.createUnresolved("proxy.example.com", 1000), "username", "password");
|
||||
ProxyDetector proxyDetector = new ProxyDetector() {
|
||||
@Nullable
|
||||
@Override
|
||||
public ProxyParameters proxyFor(SocketAddress targetServerAddress) {
|
||||
if (targetServerAddress == addr1) {
|
||||
return proxy;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
createInternalSubChannelWithProxy(proxyDetector, addr1);
|
||||
assertEquals(ConnectivityState.IDLE, internalSubchannel.getState());
|
||||
assertNoCallbackInvoke();
|
||||
assertNull(internalSubchannel.obtainActiveTransport());
|
||||
assertExactCallbackInvokes("onStateChange:CONNECTING");
|
||||
assertEquals(ConnectivityState.CONNECTING, internalSubchannel.getState());
|
||||
verify(mockTransportFactory).newClientTransport(
|
||||
eq(addr1), eq(AUTHORITY), eq(USER_AGENT), eq(proxy));
|
||||
}
|
||||
|
||||
private void createInternalSubchannel(SocketAddress ... addrs) {
|
||||
createInternalSubChannelWithProxy(ProxyDetector.NOOP_INSTANCE, addrs);
|
||||
}
|
||||
|
||||
private void createInternalSubChannelWithProxy(
|
||||
ProxyDetector proxyDetector, SocketAddress ... addrs) {
|
||||
addressGroup = new EquivalentAddressGroup(Arrays.asList(addrs));
|
||||
internalSubchannel = new InternalSubchannel(addressGroup, AUTHORITY, USER_AGENT,
|
||||
mockBackoffPolicyProvider, mockTransportFactory, fakeClock.getScheduledExecutorService(),
|
||||
fakeClock.getStopwatchSupplier(), channelExecutor, mockInternalSubchannelCallback);
|
||||
fakeClock.getStopwatchSupplier(), channelExecutor, mockInternalSubchannelCallback,
|
||||
proxyDetector);
|
||||
}
|
||||
|
||||
private void assertNoCallbackInvoke() {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ public class ManagedChannelImplIdlenessTest {
|
|||
private final FakeClock oobExecutor = new FakeClock();
|
||||
private static final String AUTHORITY = "fakeauthority";
|
||||
private static final String USER_AGENT = "fakeagent";
|
||||
private static final ProxyParameters NO_PROXY = null;
|
||||
private static final long IDLE_TIMEOUT_SECONDS = 30;
|
||||
private ManagedChannelImpl channel;
|
||||
|
||||
|
|
@ -141,7 +142,8 @@ public class ManagedChannelImplIdlenessTest {
|
|||
channel = new ManagedChannelImpl(
|
||||
builder, mockTransportFactory, new FakeBackoffPolicyProvider(),
|
||||
oobExecutorPool, timer.getStopwatchSupplier(),
|
||||
Collections.<ClientInterceptor>emptyList());
|
||||
Collections.<ClientInterceptor>emptyList(),
|
||||
ProxyDetector.NOOP_INSTANCE);
|
||||
newTransports = TestUtils.captureTransports(mockTransportFactory);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
|
@ -155,7 +157,7 @@ public class ManagedChannelImplIdlenessTest {
|
|||
// Verify the initial idleness
|
||||
verify(mockLoadBalancerFactory, never()).newLoadBalancer(any(Helper.class));
|
||||
verify(mockTransportFactory, never()).newClientTransport(
|
||||
any(SocketAddress.class), anyString(), anyString());
|
||||
any(SocketAddress.class), anyString(), anyString(), any(ProxyParameters.class));
|
||||
verify(mockNameResolver, never()).start(any(NameResolver.Listener.class));
|
||||
}
|
||||
|
||||
|
|
@ -352,11 +354,13 @@ public class ManagedChannelImplIdlenessTest {
|
|||
// Now make an RPC on an OOB channel
|
||||
ManagedChannel oob = helper.createOobChannel(servers.get(0), "oobauthority");
|
||||
verify(mockTransportFactory, never())
|
||||
.newClientTransport(any(SocketAddress.class), same("oobauthority"), same(USER_AGENT));
|
||||
.newClientTransport(any(SocketAddress.class), same("oobauthority"), same(USER_AGENT),
|
||||
same(NO_PROXY));
|
||||
ClientCall<String, Integer> oobCall = oob.newCall(method, CallOptions.DEFAULT);
|
||||
oobCall.start(mockCallListener2, new Metadata());
|
||||
verify(mockTransportFactory)
|
||||
.newClientTransport(any(SocketAddress.class), same("oobauthority"), same(USER_AGENT));
|
||||
.newClientTransport(any(SocketAddress.class), same("oobauthority"), same(USER_AGENT),
|
||||
same(NO_PROXY));
|
||||
MockClientTransportInfo oobTransportInfo = newTransports.poll();
|
||||
assertEquals(0, newTransports.size());
|
||||
// The OOB transport reports in-use state
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ public class ManagedChannelImplTest {
|
|||
private final String serviceName = "fake.example.com";
|
||||
private final String authority = serviceName;
|
||||
private final String userAgent = "userAgent";
|
||||
private final ProxyParameters noProxy = null;
|
||||
private final String target = "fake://" + serviceName;
|
||||
private URI expectedUri;
|
||||
private final SocketAddress socketAddress = new SocketAddress() {};
|
||||
|
|
@ -213,7 +214,7 @@ public class ManagedChannelImplTest {
|
|||
checkState(channel == null);
|
||||
channel = new ManagedChannelImpl(
|
||||
builder, mockTransportFactory, new FakeBackoffPolicyProvider(),
|
||||
oobExecutorPool, timer.getStopwatchSupplier(), interceptors);
|
||||
oobExecutorPool, timer.getStopwatchSupplier(), interceptors, ProxyDetector.NOOP_INSTANCE);
|
||||
|
||||
if (requestConnection) {
|
||||
// Force-exit the initial idle-mode
|
||||
|
|
@ -328,7 +329,7 @@ public class ManagedChannelImplTest {
|
|||
Subchannel subchannel = helper.createSubchannel(addressGroup, Attributes.EMPTY);
|
||||
subchannel.requestConnection();
|
||||
verify(mockTransportFactory).newClientTransport(
|
||||
any(SocketAddress.class), any(String.class), any(String.class));
|
||||
any(SocketAddress.class), any(String.class), any(String.class), any(ProxyParameters.class));
|
||||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
verify(mockTransport).start(any(ManagedClientTransport.Listener.class));
|
||||
|
|
@ -349,7 +350,7 @@ public class ManagedChannelImplTest {
|
|||
// First RPC, will be pending
|
||||
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
|
||||
verify(mockTransportFactory).newClientTransport(
|
||||
any(SocketAddress.class), any(String.class), any(String.class));
|
||||
any(SocketAddress.class), any(String.class), any(String.class), any(ProxyParameters.class));
|
||||
call.start(mockCallListener, headers);
|
||||
|
||||
verify(mockTransport, never())
|
||||
|
|
@ -437,7 +438,7 @@ public class ManagedChannelImplTest {
|
|||
verifyNoMoreInteractions(oobExecutorPool);
|
||||
|
||||
verify(mockTransportFactory).newClientTransport(
|
||||
any(SocketAddress.class), any(String.class), any(String.class));
|
||||
any(SocketAddress.class), any(String.class), any(String.class), any(ProxyParameters.class));
|
||||
verify(mockTransportFactory).close();
|
||||
verify(mockTransport, atLeast(0)).getLogId();
|
||||
verifyNoMoreInteractions(mockTransport);
|
||||
|
|
@ -459,7 +460,7 @@ public class ManagedChannelImplTest {
|
|||
subchannel1.requestConnection();
|
||||
subchannel2.requestConnection();
|
||||
verify(mockTransportFactory, times(2)).newClientTransport(
|
||||
any(SocketAddress.class), any(String.class), any(String.class));
|
||||
any(SocketAddress.class), any(String.class), any(String.class), any(ProxyParameters.class));
|
||||
MockClientTransportInfo transportInfo1 = transports.poll();
|
||||
MockClientTransportInfo transportInfo2 = transports.poll();
|
||||
|
||||
|
|
@ -522,10 +523,10 @@ public class ManagedChannelImplTest {
|
|||
// Make the transport available
|
||||
Subchannel subchannel = helper.createSubchannel(addressGroup, Attributes.EMPTY);
|
||||
verify(mockTransportFactory, never()).newClientTransport(
|
||||
any(SocketAddress.class), any(String.class), any(String.class));
|
||||
any(SocketAddress.class), any(String.class), any(String.class), any(ProxyParameters.class));
|
||||
subchannel.requestConnection();
|
||||
verify(mockTransportFactory).newClientTransport(
|
||||
any(SocketAddress.class), any(String.class), any(String.class));
|
||||
any(SocketAddress.class), any(String.class), any(String.class), any(ProxyParameters.class));
|
||||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
|
|
@ -665,9 +666,11 @@ public class ManagedChannelImplTest {
|
|||
|
||||
// The channel will starts with the first address (badAddress)
|
||||
verify(mockTransportFactory)
|
||||
.newClientTransport(same(badAddress), any(String.class), any(String.class));
|
||||
.newClientTransport(same(badAddress), any(String.class), any(String.class),
|
||||
any(ProxyParameters.class));
|
||||
verify(mockTransportFactory, times(0))
|
||||
.newClientTransport(same(goodAddress), any(String.class), any(String.class));
|
||||
.newClientTransport(same(goodAddress), any(String.class), any(String.class),
|
||||
any(ProxyParameters.class));
|
||||
|
||||
MockClientTransportInfo badTransportInfo = transports.poll();
|
||||
// Which failed to connect
|
||||
|
|
@ -676,7 +679,8 @@ public class ManagedChannelImplTest {
|
|||
|
||||
// The channel then try the second address (goodAddress)
|
||||
verify(mockTransportFactory)
|
||||
.newClientTransport(same(goodAddress), any(String.class), any(String.class));
|
||||
.newClientTransport(same(goodAddress), any(String.class), any(String.class),
|
||||
any(ProxyParameters.class));
|
||||
MockClientTransportInfo goodTransportInfo = transports.poll();
|
||||
when(goodTransportInfo.transport.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class)))
|
||||
|
|
@ -807,15 +811,18 @@ public class ManagedChannelImplTest {
|
|||
|
||||
// Connecting to server1, which will fail
|
||||
verify(mockTransportFactory)
|
||||
.newClientTransport(same(addr1), any(String.class), any(String.class));
|
||||
.newClientTransport(same(addr1), any(String.class), any(String.class),
|
||||
any(ProxyParameters.class));
|
||||
verify(mockTransportFactory, times(0))
|
||||
.newClientTransport(same(addr2), any(String.class), any(String.class));
|
||||
.newClientTransport(same(addr2), any(String.class), any(String.class),
|
||||
any(ProxyParameters.class));
|
||||
MockClientTransportInfo transportInfo1 = transports.poll();
|
||||
transportInfo1.listener.transportShutdown(Status.UNAVAILABLE);
|
||||
|
||||
// Connecting to server2, which will fail too
|
||||
verify(mockTransportFactory)
|
||||
.newClientTransport(same(addr2), any(String.class), any(String.class));
|
||||
.newClientTransport(same(addr2), any(String.class), any(String.class),
|
||||
any(ProxyParameters.class));
|
||||
MockClientTransportInfo transportInfo2 = transports.poll();
|
||||
Status server2Error = Status.UNAVAILABLE.withDescription("Server2 failed to connect");
|
||||
transportInfo2.listener.transportShutdown(server2Error);
|
||||
|
|
@ -863,20 +870,22 @@ public class ManagedChannelImplTest {
|
|||
|
||||
// requestConnection()
|
||||
verify(mockTransportFactory, never()).newClientTransport(
|
||||
any(SocketAddress.class), any(String.class), any(String.class));
|
||||
any(SocketAddress.class), any(String.class), any(String.class), any(ProxyParameters.class));
|
||||
sub1.requestConnection();
|
||||
verify(mockTransportFactory).newClientTransport(socketAddress, authority, userAgent);
|
||||
verify(mockTransportFactory).newClientTransport(socketAddress, authority, userAgent, noProxy);
|
||||
MockClientTransportInfo transportInfo1 = transports.poll();
|
||||
assertNotNull(transportInfo1);
|
||||
|
||||
sub2.requestConnection();
|
||||
verify(mockTransportFactory, times(2)).newClientTransport(socketAddress, authority, userAgent);
|
||||
verify(mockTransportFactory, times(2)).newClientTransport(socketAddress, authority, userAgent,
|
||||
noProxy);
|
||||
MockClientTransportInfo transportInfo2 = transports.poll();
|
||||
assertNotNull(transportInfo2);
|
||||
|
||||
sub1.requestConnection();
|
||||
sub2.requestConnection();
|
||||
verify(mockTransportFactory, times(2)).newClientTransport(socketAddress, authority, userAgent);
|
||||
verify(mockTransportFactory, times(2)).newClientTransport(socketAddress, authority, userAgent,
|
||||
noProxy);
|
||||
|
||||
// shutdown() has a delay
|
||||
sub1.shutdown();
|
||||
|
|
@ -944,7 +953,7 @@ public class ManagedChannelImplTest {
|
|||
sub2.shutdown();
|
||||
assertTrue(channel.isTerminated());
|
||||
verify(mockTransportFactory, never()).newClientTransport(any(SocketAddress.class), anyString(),
|
||||
anyString());
|
||||
anyString(), any(ProxyParameters.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -959,7 +968,7 @@ public class ManagedChannelImplTest {
|
|||
// Therefore, channel is terminated without relying on LoadBalancer to shutdown subchannels.
|
||||
assertTrue(channel.isTerminated());
|
||||
verify(mockTransportFactory, never()).newClientTransport(any(SocketAddress.class), anyString(),
|
||||
anyString());
|
||||
anyString(), any(ProxyParameters.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -977,7 +986,8 @@ public class ManagedChannelImplTest {
|
|||
Metadata headers = new Metadata();
|
||||
ClientCall<String, Integer> call = oob1.newCall(method, CallOptions.DEFAULT);
|
||||
call.start(mockCallListener, headers);
|
||||
verify(mockTransportFactory).newClientTransport(socketAddress, "oob1authority", userAgent);
|
||||
verify(mockTransportFactory).newClientTransport(socketAddress, "oob1authority", userAgent,
|
||||
noProxy);
|
||||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
assertNotNull(transportInfo);
|
||||
|
||||
|
|
@ -998,7 +1008,7 @@ public class ManagedChannelImplTest {
|
|||
oob1.newCall(method, CallOptions.DEFAULT.withWaitForReady());
|
||||
call3.start(mockCallListener3, headers);
|
||||
verify(mockTransportFactory, times(2)).newClientTransport(
|
||||
socketAddress, "oob1authority", userAgent);
|
||||
socketAddress, "oob1authority", userAgent, noProxy);
|
||||
transportInfo = transports.poll();
|
||||
assertNotNull(transportInfo);
|
||||
|
||||
|
|
@ -1103,7 +1113,7 @@ public class ManagedChannelImplTest {
|
|||
assertTrue(oob2.isTerminated());
|
||||
assertTrue(channel.isTerminated());
|
||||
verify(mockTransportFactory, never()).newClientTransport(any(SocketAddress.class), anyString(),
|
||||
anyString());
|
||||
anyString(), any(ProxyParameters.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1118,7 +1128,7 @@ public class ManagedChannelImplTest {
|
|||
// Channel's shutdownNow() will call shutdownNow() on all subchannels and oobchannels.
|
||||
// Therefore, channel is terminated without relying on LoadBalancer to shutdown oobchannels.
|
||||
verify(mockTransportFactory, never()).newClientTransport(any(SocketAddress.class), anyString(),
|
||||
anyString());
|
||||
anyString(), any(ProxyParameters.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1168,7 +1178,7 @@ public class ManagedChannelImplTest {
|
|||
Subchannel subchannel = helper.createSubchannel(addressGroup, Attributes.EMPTY);
|
||||
subchannel.requestConnection();
|
||||
verify(mockTransportFactory).newClientTransport(
|
||||
same(socketAddress), eq(authority), eq(userAgent));
|
||||
same(socketAddress), eq(authority), eq(userAgent), eq(noProxy));
|
||||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
final ConnectionClientTransport transport = transportInfo.transport;
|
||||
when(transport.getAttributes()).thenReturn(Attributes.EMPTY);
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ final class TestUtils {
|
|||
return mockTransport;
|
||||
}
|
||||
}).when(mockTransportFactory)
|
||||
.newClientTransport(any(SocketAddress.class), any(String.class), any(String.class));
|
||||
.newClientTransport(any(SocketAddress.class), any(String.class), any(String.class),
|
||||
any(ProxyParameters.class));
|
||||
|
||||
return captor;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package io.grpc.netty;
|
||||
|
||||
import io.grpc.Internal;
|
||||
import io.grpc.internal.ProxyParameters;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
|
|
@ -44,7 +45,8 @@ public final class InternalNettyChannelBuilder {
|
|||
extends NettyChannelBuilder.TransportCreationParamsFilterFactory {
|
||||
@Override
|
||||
TransportCreationParamsFilter create(
|
||||
SocketAddress targetServerAddress, String authority, String userAgent);
|
||||
SocketAddress targetServerAddress, String authority, String userAgent,
|
||||
ProxyParameters proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import io.grpc.internal.ClientTransportFactory;
|
|||
import io.grpc.internal.ConnectionClientTransport;
|
||||
import io.grpc.internal.GrpcUtil;
|
||||
import io.grpc.internal.KeepAliveManager;
|
||||
import io.grpc.internal.ProxyParameters;
|
||||
import io.grpc.internal.SharedResourceHolder;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelOption;
|
||||
|
|
@ -341,18 +342,13 @@ public final class NettyChannelBuilder
|
|||
static ProtocolNegotiator createProtocolNegotiator(
|
||||
String authority,
|
||||
NegotiationType negotiationType,
|
||||
SslContext sslContext) {
|
||||
SslContext sslContext,
|
||||
ProxyParameters proxy) {
|
||||
ProtocolNegotiator negotiator =
|
||||
createProtocolNegotiatorByType(authority, negotiationType, sslContext);
|
||||
String proxy = System.getenv("GRPC_PROXY_EXP");
|
||||
if (proxy != null) {
|
||||
String[] parts = proxy.split(":", 2);
|
||||
int port = 80;
|
||||
if (parts.length > 1) {
|
||||
port = Integer.parseInt(parts[1]);
|
||||
}
|
||||
InetSocketAddress proxyAddress = new InetSocketAddress(parts[0], port);
|
||||
negotiator = ProtocolNegotiators.httpProxy(proxyAddress, null, null, negotiator);
|
||||
negotiator = ProtocolNegotiators.httpProxy(
|
||||
proxy.proxyAddress, proxy.username, proxy.password, negotiator);
|
||||
}
|
||||
return negotiator;
|
||||
}
|
||||
|
|
@ -406,7 +402,10 @@ public final class NettyChannelBuilder
|
|||
interface TransportCreationParamsFilterFactory {
|
||||
@CheckReturnValue
|
||||
TransportCreationParamsFilter create(
|
||||
SocketAddress targetServerAddress, String authority, @Nullable String userAgent);
|
||||
SocketAddress targetServerAddress,
|
||||
String authority,
|
||||
@Nullable String userAgent,
|
||||
@Nullable ProxyParameters proxy);
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
|
|
@ -472,11 +471,12 @@ public final class NettyChannelBuilder
|
|||
|
||||
@Override
|
||||
public ConnectionClientTransport newClientTransport(
|
||||
SocketAddress serverAddress, String authority, @Nullable String userAgent) {
|
||||
SocketAddress serverAddress, String authority, @Nullable String userAgent,
|
||||
@Nullable ProxyParameters proxy) {
|
||||
checkState(!closed, "The transport factory is closed.");
|
||||
|
||||
TransportCreationParamsFilter dparams =
|
||||
transportCreationParamsFilterFactory.create(serverAddress, authority, userAgent);
|
||||
transportCreationParamsFilterFactory.create(serverAddress, authority, userAgent, proxy);
|
||||
|
||||
final AtomicBackoff.State keepAliveTimeNanosState = keepAliveTimeNanos.getState();
|
||||
Runnable tooManyPingsRunnable = new Runnable() {
|
||||
|
|
@ -528,8 +528,12 @@ public final class NettyChannelBuilder
|
|||
|
||||
@Override
|
||||
public TransportCreationParamsFilter create(
|
||||
SocketAddress targetServerAddress, String authority, String userAgent) {
|
||||
return new DynamicNettyTransportParams(targetServerAddress, authority, userAgent);
|
||||
SocketAddress targetServerAddress,
|
||||
String authority,
|
||||
String userAgent,
|
||||
ProxyParameters proxyParams) {
|
||||
return new DynamicNettyTransportParams(
|
||||
targetServerAddress, authority, userAgent, proxyParams);
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
|
|
@ -538,12 +542,17 @@ public final class NettyChannelBuilder
|
|||
private final SocketAddress targetServerAddress;
|
||||
private final String authority;
|
||||
@Nullable private final String userAgent;
|
||||
private ProxyParameters proxyParams;
|
||||
|
||||
private DynamicNettyTransportParams(
|
||||
SocketAddress targetServerAddress, String authority, String userAgent) {
|
||||
SocketAddress targetServerAddress,
|
||||
String authority,
|
||||
String userAgent,
|
||||
ProxyParameters proxyParams) {
|
||||
this.targetServerAddress = targetServerAddress;
|
||||
this.authority = authority;
|
||||
this.userAgent = userAgent;
|
||||
this.proxyParams = proxyParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -563,7 +572,7 @@ public final class NettyChannelBuilder
|
|||
|
||||
@Override
|
||||
public ProtocolNegotiator getProtocolNegotiator() {
|
||||
return createProtocolNegotiator(authority, negotiationType, sslContext);
|
||||
return createProtocolNegotiator(authority, negotiationType, sslContext, proxyParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue;
|
|||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.internal.ProxyParameters;
|
||||
import io.grpc.netty.InternalNettyChannelBuilder.OverrideAuthorityChecker;
|
||||
import io.grpc.netty.ProtocolNegotiators.TlsNegotiator;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
|
|
@ -39,6 +40,7 @@ public class NettyChannelBuilderTest {
|
|||
|
||||
@Rule public final ExpectedException thrown = ExpectedException.none();
|
||||
private final SslContext noSslContext = null;
|
||||
private final ProxyParameters noProxy = null;
|
||||
|
||||
private void shutdown(ManagedChannel mc) throws Exception {
|
||||
mc.shutdownNow();
|
||||
|
|
@ -141,7 +143,8 @@ public class NettyChannelBuilderTest {
|
|||
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiator(
|
||||
"authority",
|
||||
NegotiationType.PLAINTEXT,
|
||||
noSslContext);
|
||||
noSslContext,
|
||||
noProxy);
|
||||
// just check that the classes are the same, and that negotiator is not null.
|
||||
assertTrue(negotiator instanceof ProtocolNegotiators.PlaintextNegotiator);
|
||||
}
|
||||
|
|
@ -151,7 +154,8 @@ public class NettyChannelBuilderTest {
|
|||
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiator(
|
||||
"authority",
|
||||
NegotiationType.PLAINTEXT_UPGRADE,
|
||||
noSslContext);
|
||||
noSslContext,
|
||||
noProxy);
|
||||
// just check that the classes are the same, and that negotiator is not null.
|
||||
assertTrue(negotiator instanceof ProtocolNegotiators.PlaintextUpgradeNegotiator);
|
||||
}
|
||||
|
|
@ -162,7 +166,8 @@ public class NettyChannelBuilderTest {
|
|||
NettyChannelBuilder.createProtocolNegotiator(
|
||||
"authority:1234",
|
||||
NegotiationType.TLS,
|
||||
noSslContext);
|
||||
noSslContext,
|
||||
noProxy);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -170,7 +175,8 @@ public class NettyChannelBuilderTest {
|
|||
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiator(
|
||||
"authority:1234",
|
||||
NegotiationType.TLS,
|
||||
GrpcSslContexts.forClient().build());
|
||||
GrpcSslContexts.forClient().build(),
|
||||
noProxy);
|
||||
|
||||
assertTrue(negotiator instanceof ProtocolNegotiators.TlsNegotiator);
|
||||
ProtocolNegotiators.TlsNegotiator n = (TlsNegotiator) negotiator;
|
||||
|
|
@ -184,7 +190,8 @@ public class NettyChannelBuilderTest {
|
|||
ProtocolNegotiator negotiator = NettyChannelBuilder.createProtocolNegotiator(
|
||||
"bad_authority",
|
||||
NegotiationType.TLS,
|
||||
GrpcSslContexts.forClient().build());
|
||||
GrpcSslContexts.forClient().build(),
|
||||
noProxy);
|
||||
|
||||
assertTrue(negotiator instanceof ProtocolNegotiators.TlsNegotiator);
|
||||
ProtocolNegotiators.TlsNegotiator n = (TlsNegotiator) negotiator;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ public class NettyTransportTest extends AbstractTransportTest {
|
|||
return clientFactory.newClientTransport(
|
||||
new InetSocketAddress("localhost", port),
|
||||
testAuthority(server),
|
||||
null /* agent */);
|
||||
null /* agent */,
|
||||
null /* proxy */);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import io.grpc.internal.ClientTransportFactory;
|
|||
import io.grpc.internal.ConnectionClientTransport;
|
||||
import io.grpc.internal.GrpcUtil;
|
||||
import io.grpc.internal.KeepAliveManager;
|
||||
import io.grpc.internal.ProxyParameters;
|
||||
import io.grpc.internal.SharedResourceHolder;
|
||||
import io.grpc.internal.SharedResourceHolder.Resource;
|
||||
import io.grpc.okhttp.internal.Platform;
|
||||
|
|
@ -403,20 +404,11 @@ public class OkHttpChannelBuilder extends
|
|||
|
||||
@Override
|
||||
public ConnectionClientTransport newClientTransport(
|
||||
SocketAddress addr, String authority, @Nullable String userAgent) {
|
||||
SocketAddress addr, String authority, @Nullable String userAgent,
|
||||
@Nullable ProxyParameters proxy) {
|
||||
if (closed) {
|
||||
throw new IllegalStateException("The transport factory is closed.");
|
||||
}
|
||||
InetSocketAddress proxyAddress = null;
|
||||
String proxy = System.getenv("GRPC_PROXY_EXP");
|
||||
if (proxy != null) {
|
||||
String[] parts = proxy.split(":", 2);
|
||||
int port = 80;
|
||||
if (parts.length > 1) {
|
||||
port = Integer.parseInt(parts[1]);
|
||||
}
|
||||
proxyAddress = new InetSocketAddress(parts[0], port);
|
||||
}
|
||||
final AtomicBackoff.State keepAliveTimeNanosState = keepAliveTimeNanos.getState();
|
||||
Runnable tooManyPingsRunnable = new Runnable() {
|
||||
@Override
|
||||
|
|
@ -425,9 +417,19 @@ public class OkHttpChannelBuilder extends
|
|||
}
|
||||
};
|
||||
InetSocketAddress inetSocketAddr = (InetSocketAddress) addr;
|
||||
OkHttpClientTransport transport = new OkHttpClientTransport(inetSocketAddr, authority,
|
||||
userAgent, executor, socketFactory, hostnameVerifier, Utils.convertSpec(connectionSpec),
|
||||
maxMessageSize, proxyAddress, null, null, tooManyPingsRunnable);
|
||||
OkHttpClientTransport transport = new OkHttpClientTransport(
|
||||
inetSocketAddr,
|
||||
authority,
|
||||
userAgent,
|
||||
executor,
|
||||
socketFactory,
|
||||
hostnameVerifier,
|
||||
Utils.convertSpec(connectionSpec),
|
||||
maxMessageSize,
|
||||
proxy == null ? null : proxy.proxyAddress,
|
||||
proxy == null ? null : proxy.username,
|
||||
proxy == null ? null : proxy.password,
|
||||
tooManyPingsRunnable);
|
||||
if (enableKeepAlive) {
|
||||
transport.enableKeepAlive(
|
||||
true, keepAliveTimeNanosState.get(), keepAliveTimeoutNanos, keepAliveWithoutCalls);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright 2017, gRPC Authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.internal;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class ProxyDetectorImplTest {
|
||||
private InetSocketAddress destination = InetSocketAddress.createUnresolved(
|
||||
"destination",
|
||||
5678
|
||||
);
|
||||
|
||||
@Mock private ProxySelector proxySelector;
|
||||
@Mock private ProxyDetectorImpl.AuthenticationProvider authenticator;
|
||||
private Supplier<ProxySelector> proxySelectorSupplier;
|
||||
private ProxyDetector proxyDetector;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
proxySelectorSupplier = new Supplier<ProxySelector>() {
|
||||
@Override
|
||||
public ProxySelector get() {
|
||||
return proxySelector;
|
||||
}
|
||||
};
|
||||
proxyDetector = new ProxyDetectorImpl(proxySelectorSupplier, authenticator, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void override_hostPort() throws Exception {
|
||||
final String overrideHost = "override";
|
||||
final int overridePort = 1234;
|
||||
HostAndPort hostPort = HostAndPort.fromParts(overrideHost, overridePort);
|
||||
ProxyDetectorImpl proxyDetector = new ProxyDetectorImpl(
|
||||
proxySelectorSupplier,
|
||||
authenticator,
|
||||
hostPort.toString());
|
||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||
assertNotNull(detected);
|
||||
assertEquals(
|
||||
new ProxyParameters(
|
||||
InetSocketAddress.createUnresolved(overrideHost, overridePort), null, null),
|
||||
detected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void override_hostOnly() throws Exception {
|
||||
final String overrideHostWithoutPort = "override";
|
||||
final int defaultPort = 80;
|
||||
ProxyDetectorImpl proxyDetector = new ProxyDetectorImpl(
|
||||
proxySelectorSupplier,
|
||||
authenticator,
|
||||
overrideHostWithoutPort);
|
||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||
assertNotNull(detected);
|
||||
assertEquals(
|
||||
new ProxyParameters(
|
||||
InetSocketAddress.createUnresolved(overrideHostWithoutPort, defaultPort), null, null),
|
||||
detected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnNullWhenNoProxy() throws Exception {
|
||||
when(proxySelector.select(any(URI.class)))
|
||||
.thenReturn(ImmutableList.of(java.net.Proxy.NO_PROXY));
|
||||
assertNull(proxyDetector.proxyFor(destination));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectProxyForUnresolved() throws Exception {
|
||||
final InetSocketAddress proxyAddress = InetSocketAddress.createUnresolved("proxy", 1234);
|
||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
|
||||
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
||||
|
||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||
assertNotNull(detected);
|
||||
assertEquals(new ProxyParameters(proxyAddress, null, null), detected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectProxyForResolved() throws Exception {
|
||||
InetSocketAddress resolved =
|
||||
new InetSocketAddress(InetAddress.getByAddress(new byte[]{10, 0, 0, 1}), 10);
|
||||
assertFalse(resolved.isUnresolved());
|
||||
destination = resolved;
|
||||
|
||||
final InetSocketAddress proxyAddress = InetSocketAddress.createUnresolved("proxy", 1234);
|
||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
|
||||
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
||||
|
||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||
assertNotNull(detected);
|
||||
assertEquals(new ProxyParameters(proxyAddress, null, null), detected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pickFirstHttpProxy() throws Exception {
|
||||
final InetSocketAddress proxyAddress = InetSocketAddress.createUnresolved("proxy1", 1111);
|
||||
InetSocketAddress otherProxy = InetSocketAddress.createUnresolved("proxy2", 2222);
|
||||
Proxy proxy1 = new java.net.Proxy(java.net.Proxy.Type.HTTP, proxyAddress);
|
||||
Proxy proxy2 = new java.net.Proxy(java.net.Proxy.Type.HTTP, otherProxy);
|
||||
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy1, proxy2));
|
||||
|
||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||
assertNotNull(detected);
|
||||
assertEquals(new ProxyParameters(proxyAddress, null, null), detected);
|
||||
}
|
||||
|
||||
// Mainly for InProcessSocketAddress
|
||||
@Test
|
||||
public void noProxyForNonInetSocket() throws Exception {
|
||||
assertNull(proxyDetector.proxyFor(mock(SocketAddress.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authRequired() throws Exception {
|
||||
final String proxyHost = "proxyhost";
|
||||
final int proxyPort = 1234;
|
||||
final InetSocketAddress proxyAddress = InetSocketAddress.createUnresolved(proxyHost, proxyPort);
|
||||
Proxy proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, proxyAddress);
|
||||
final String proxyUser = "testuser";
|
||||
final String proxyPassword = "testpassword";
|
||||
PasswordAuthentication auth = new PasswordAuthentication(
|
||||
proxyUser,
|
||||
proxyPassword.toCharArray());
|
||||
when(authenticator.requestPasswordAuthentication(
|
||||
any(String.class),
|
||||
any(InetAddress.class),
|
||||
any(Integer.class),
|
||||
any(String.class),
|
||||
any(String.class),
|
||||
any(String.class))).thenReturn(auth);
|
||||
when(proxySelector.select(any(URI.class))).thenReturn(ImmutableList.of(proxy));
|
||||
|
||||
ProxyParameters detected = proxyDetector.proxyFor(destination);
|
||||
assertNotNull(detected);
|
||||
assertEquals(new ProxyParameters(proxyAddress, proxyUser, proxyPassword), detected);
|
||||
}
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ public class OkHttpChannelBuilderTest {
|
|||
public void usePlaintext_newClientTransportAllowed() {
|
||||
OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("host", 1234).usePlaintext(true);
|
||||
builder.buildTransportFactory().newClientTransport(new InetSocketAddress(5678),
|
||||
"dummy_authority", "dummy_userAgent");
|
||||
"dummy_authority", "dummy_userAgent", null /* proxy */);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ public class OkHttpTransportTest extends AbstractTransportTest {
|
|||
return clientFactory.newClientTransport(
|
||||
new InetSocketAddress("::1", port),
|
||||
testAuthority(server),
|
||||
null /* agent */);
|
||||
null /* agent */,
|
||||
null /* proxy */);
|
||||
}
|
||||
|
||||
// TODO(ejona): Flaky/Broken
|
||||
|
|
|
|||
|
|
@ -40,6 +40,6 @@ public abstract class AbstractClientTransportFactoryTest {
|
|||
ClientTransportFactory transportFactory = newClientTransportFactory();
|
||||
transportFactory.close();
|
||||
transportFactory.newClientTransport(
|
||||
new InetSocketAddress("localhost", 12345), "localhost:" + 12345, "agent");
|
||||
new InetSocketAddress("localhost", 12345), "localhost:" + 12345, "agent", null);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue