in httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ProxyClient.java [142:222]
public Socket tunnel(
final HttpHost proxy,
final HttpHost target,
final Credentials credentials) throws IOException, HttpException {
Args.notNull(proxy, "Proxy host");
Args.notNull(target, "Target host");
Args.notNull(credentials, "Credentials");
HttpHost host = target;
if (host.getPort() <= 0) {
host = new HttpHost(host.getSchemeName(), host.getHostName(), 80);
}
final HttpRoute route = new HttpRoute(
host,
null,
proxy, false, TunnelType.TUNNELLED, LayerType.PLAIN);
final ManagedHttpClientConnection conn = this.connFactory.createConnection(null);
final HttpContext context = new BasicHttpContext();
ClassicHttpResponse response;
final ClassicHttpRequest connect = new BasicClassicHttpRequest(Method.CONNECT, proxy, host.toHostString());
final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(proxy), credentials);
// Populate the execution context
context.setAttribute(HttpCoreContext.HTTP_REQUEST, connect);
context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
context.setAttribute(HttpClientContext.CREDS_PROVIDER, credsProvider);
context.setAttribute(HttpClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry);
context.setAttribute(HttpClientContext.REQUEST_CONFIG, this.requestConfig);
this.requestExec.preProcess(connect, this.httpProcessor, context);
for (;;) {
if (!conn.isOpen()) {
final Socket socket = new Socket(proxy.getHostName(), proxy.getPort());
conn.bind(socket);
}
this.authenticator.addAuthResponse(proxy, ChallengeType.PROXY, connect, this.proxyAuthExchange, context);
response = this.requestExec.execute(connect, conn, context);
final int status = response.getCode();
if (status < 200) {
throw new HttpException("Unexpected response to CONNECT request: " + response);
}
if (this.authenticator.isChallenged(proxy, ChallengeType.PROXY, response, this.proxyAuthExchange, context)) {
if (this.authenticator.updateAuthState(proxy, ChallengeType.PROXY, response,
this.proxyAuthStrategy, this.proxyAuthExchange, context)) {
// Retry request
if (this.reuseStrategy.keepAlive(connect, response, context)) {
// Consume response content
final HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
} else {
conn.close();
}
// discard previous auth header
connect.removeHeaders(HttpHeaders.PROXY_AUTHORIZATION);
} else {
break;
}
} else {
break;
}
}
final int status = response.getCode();
if (status > 299) {
// Buffer response content
final HttpEntity entity = response.getEntity();
final String responseMessage = entity != null ? EntityUtils.toString(entity) : null;
conn.close();
throw new TunnelRefusedException("CONNECT refused by proxy: " + new StatusLine(response), responseMessage);
}
return conn.getSocket();
}