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: dev-unsubscr...@hc.apache.org For additional commands, e-mail: dev-h...@hc.apache.org