Hello,
I’m trying to use the HttpClient from Jetty 9.1.1.v20140108 to tunnel through a proxy-server using proxy-authentication.
I see that the Jetty client connects to the proxy without credentials, upon which the proxy sends a 407 “proxy authentication required” response back. The Jetty client then looks in the HTTP authentication store for suitable credentials
(with matching realm & URI) to use in the next request on the connection.
The problem is, some proxies, such as Squid promptly drop the connection upon authentication failure – and there is no opportunity to submit a second request with the proxy-authenticate header.
Following are the request & response logged by Jetty which shows that no authentication header was initially sent. The “Connection: close” header from Squid shows that the connection is dropped by Squid on an auth failures.
17:56:11.159 [HttpClient@469537924-12-selector-ClientSelectorManager@18688fe1/0] DEBUG org.eclipse.jetty.client.HttpSender - Request headers HttpRequest[CONNECT
hawker.flyer.qagood.com:443 HTTP/1.1]@7a7ac5
Accept-Encoding: gzip
Host: hawker.flyer.qagood.com:443
User-Agent: Jetty/9.1.1.v20140108
17:56:11.182 [HttpClient@469537924-18] DEBUG o.eclipse.jetty.client.HttpReceiver - Response headers HttpResponse[HTTP/1.0 407 Proxy Authentication
Required]@4838eb55
Server: squid/2.7.STABLE8
Date: Tue, 11 Feb 2014 01:56:11 GMT
Content-Type: text/html
Content-Length: 1373
X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
Proxy-Authenticate: Basic realm="Squid proxy-caching web server"
X-Cache: MISS from GASLAMP03.ocs.qagood.com
X-Cache-Lookup: NONE from GASLAMP03.ocs.qagood.com:3128
Via: 1.0 GASLAMP03.ocs.qagood.com:3128 (squid/2.7.STABLE8)
Connection: close
This is the Jetty HttpClient related code that creates the CONNECT request & sends it to the proxy, and clearly there is no authentication header supplied at this stage:
org.eclipse.jetty.client.HttpProxy.HttpProxyClientConnectionFactory.ProxyPromise.tunnel(HttpDestination, Connection)
private void tunnel(HttpDestination destination, final Connection connection)
{
String target = destination.getOrigin().getAddress().asString();
Origin.Address proxyAddress = destination.getConnectAddress();
HttpClient httpClient = destination.getHttpClient();
Request connect = httpClient.newRequest(proxyAddress.getHost(), proxyAddress.getPort())
.scheme(HttpScheme.HTTP.asString())
.method(HttpMethod.CONNECT)
.path(target)
.header(HttpHeader.HOST, target)
.timeout(httpClient.getConnectTimeout(), TimeUnit.MILLISECONDS);
Is there a way to make this scenario work? What seems to be required is the ability to ‘pre-authenticate’.
I’ve also tried using the HttpClient.newRequest().method(HttpMethod.CONNECT) etc. to pre-authenticate myself (supplying the Proxy-Authenticate header
directly). I am able to establish the tunnel & receive a 200 response from the proxy server -- but I’m not sure how I can access the underlying HTTP connection to submit the next (real) request.
The tunnel() method shown above has access to the Connection, and my code does not.
Any advice is appreciated.
Thanks,
Gautam.