Thomas Beckers created HTTPCLIENT-2373:
------------------------------------------
Summary: HTTP proxy returns 400 when connection was established
before
Key: HTTPCLIENT-2373
URL: https://issues.apache.org/jira/browse/HTTPCLIENT-2373
Project: HttpComponents HttpClient
Issue Type: Bug
Components: HttpClient (classic)
Affects Versions: 5.4.4
Reporter: Thomas Beckers
The following code makes a HTTP request that returns 400 from the proxy (Squid).
There is no issue when no connection is established before
(DO_SOCKET_CONNECT_BEFORE = false). The socket connection is done to perform
some sort of connection test before making the actual HTTP request.
Equivalent code is working in Http Client 4.
{code:java}
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory;
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.io.LeaseRequest;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.routing.HttpRoutePlanner;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
import org.apache.hc.client5.http.ssl.TlsSocketStrategy;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class HttpClientIssue {
private static final String PROXY_HOST = "<SQUID_HOST>";
private static final int PROXY_PORT = 3128;
private static final URI TARGET_URI =
URI.create("https://workspace.google.com:443/intl/de/gmail/");
private static boolean DO_SOCKET_CONNECT_BEFORE = true;
public static void main(String[] args) throws IOException,
ExecutionException, InterruptedException, TimeoutException {
Client client = createHttpClient();
if (DO_SOCKET_CONNECT_BEFORE) {
ConnectionEndpoint connectionEndpoint = null;
try {
HttpHost targetHost = new HttpHost(TARGET_URI.getScheme(),
TARGET_URI.getHost(), TARGET_URI.getPort());
HttpRoute route = determineRouteViaHttpProxy(targetHost);
LeaseRequest connectionRequest =
client.connectionManager().lease(null, route, Timeout.ofMilliseconds(15_000),
null);
connectionEndpoint =
connectionRequest.get(Timeout.ofMilliseconds(15_000));
HttpClientContext context = HttpClientContext.create();
context.setRoute(route);
client.connectionManager().connect(connectionEndpoint,
Timeout.ofMilliseconds(15_000), context);
if (!connectionEndpoint.isConnected()) {
throw new RuntimeException();
}
} finally {
client.connectionManager().release(connectionEndpoint, null,
TimeValue.of(0, TimeUnit.SECONDS));
}
}
HttpGet request = new HttpGet(TARGET_URI);
String result = client.client()
.execute(request, response -> new
String(response.getEntity().getContent().readAllBytes()));
System.out.println(result);
}
private record Client(CloseableHttpClient client,
HttpClientConnectionManager connectionManager) {
}
private static class HttpProxyRoutePlanner implements HttpRoutePlanner {
@Override
public HttpRoute determineRoute(HttpHost targetHost, HttpContext
context) {
HttpHost proxyHost = new HttpHost(PROXY_HOST, PROXY_PORT);
boolean isSecure =
"https".equalsIgnoreCase(targetHost.getSchemeName());
return new HttpRoute(targetHost, null, proxyHost, isSecure);
}
}
private static HttpRoute determineRouteViaHttpProxy(HttpHost targetHost) {
HttpRoutePlanner routePlanner = new HttpProxyRoutePlanner();
HttpRoute httpRoute;
try {
httpRoute = routePlanner.determineRoute(targetHost, null, null);
} catch (HttpException e) {
throw new RuntimeException(e.getMessage(), e);
}
return httpRoute;
}
private static Client createHttpClient() {
Http1Config http1Config = Http1Config.custom()
.setVersion(HttpVersion.HTTP_1_1)
.build();
ManagedHttpClientConnectionFactory managedHttpClientConnectionFactory =
ManagedHttpClientConnectionFactory.builder()
.http1Config(http1Config)
.build();
ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setConnectTimeout(15_000, TimeUnit.MILLISECONDS)
.setSocketTimeout(15_000, TimeUnit.MILLISECONDS)
.build();
RequestConfig requestConfig = RequestConfig.custom()
.setExpectContinueEnabled(false)
.build();
BasicHttpClientConnectionManager connectionManager =
BasicHttpClientConnectionManager.create(createSchemeRegistry(),
managedHttpClientConnectionFactory);
connectionManager.setConnectionConfig(connectionConfig);
connectionManager.setSocketConfig(SocketConfig.custom().setSoTimeout(15_000,
TimeUnit.MILLISECONDS).build());
HttpClientBuilder clientBuilder = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.setRoutePlanner(
new
DefaultProxyRoutePlanner(new HttpHost(PROXY_HOST, PROXY_PORT)));
return new Client(clientBuilder.build(), connectionManager);
}
private static Registry<TlsSocketStrategy> createSchemeRegistry() {
RegistryBuilder<TlsSocketStrategy> registryBuilder =
RegistryBuilder.create();
registryBuilder.register("https",
DefaultClientTlsStrategy.createSystemDefault());
return registryBuilder.build();
}
}
{code}
(This code is a boiled down version of the real code in our application)
Is this a bug or are we misuning Http Client?
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]