[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [jetty-users] HttpClient proxy tunnel pre-authentication
|
That worked well - thank you!
However I'm hitting a second problem, this time with Digest auth to the proxy. This appears to be a bug in HttpProxyClientConnectionFactory.ProxyPromise.tunnel.
When tunnel is called, in my case, the target is being set to "hawker.flyer.qagood.com:443".
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);
So when path(target) is invoked we wind up calling URI.create("hawker.flyer.qagood.com:443")
public Request path(String path)
{
URI uri = URI.create(path);
String rawPath = uri.getRawPath();
if (uri.isOpaque())
rawPath = path;
if (rawPath == null)
rawPath = "";
this.path = rawPath;
This produces a uri with scheme = "hawker.flyer.qagood.com" which is wrong and this.path ends up null (via uri.getRawPath()).
Later on, that causes a NullPointerException when buildUri tries to use the path:
private URI buildURI(boolean withQuery)
{
String path = getPath();
String query = getQuery();
if (query != null && withQuery)
path += "?" + query;
URI result = URI.create(path);
The stacktrace for the exception is:
Thread [HttpClient@774730085-17] (Suspended (exception NullPointerException))
URI$Parser.parse(boolean) line: not available
URI.<init>(String) line: not available
URI.create(String) line: not available
HttpRequest.buildURI(boolean) line: 691
HttpRequest.getURI() line: 191
DigestAuthentication$DigestResult.apply(Request) line: 223
AuthenticationProtocolHandler$AuthenticationListener.onComplete(Result) line: 145
ResponseNotifier.notifyComplete(Response$CompleteListener, Result) line: 215
ResponseNotifier.notifyComplete(List<ResponseListener>, Result) line: 207
HttpReceiverOverHTTP(HttpReceiver).responseSuccess(HttpExchange) line: 350
HttpReceiverOverHTTP.messageComplete() line: 196
HttpParser.parseNext(ByteBuffer) line: 1224
HttpReceiverOverHTTP.parse(ByteBuffer) line: 116
HttpReceiverOverHTTP.receive() line: 82
HttpChannelOverHTTP.receive() line: 75
HttpConnectionOverHTTP.onFillable() line: 103
AbstractConnection$1.run() line: 505
QueuedThreadPool.runJob(Runnable) line: 607
QueuedThreadPool$3.run() line: 536
Thread.run() line: not available
-----Original Message-----
From: jetty-users-bounces@xxxxxxxxxxx [mailto:jetty-users-bounces@xxxxxxxxxxx] On Behalf Of Simone Bordet
Sent: Tuesday, February 11, 2014 2:32 AM
To: JETTY user mailing list
Subject: Re: [jetty-users] HttpClient proxy tunnel pre-authentication
Hi,
On Tue, Feb 11, 2014 at 3:07 AM, Gautam Pulla <gpulla@xxxxxxxx> wrote:
> 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.Pr
> oxyPromise.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);
Confirmed, it's a bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=427878
> Is there a way to make this scenario work? What seems to be required
> is the ability to ‘pre-authenticate’.
Yes, that exposes bug2 :( but you can work it around in this way:
final URI uri = URI.create("http://localhost:" + proxyPort()); final String value = "Basic " + B64Code.encode("user:password", StandardCharsets.ISO_8859_1); httpClient.getAuthenticationStore().addAuthenticationResult(new
Authentication.Result()
{
@Override
public URI getURI()
{
return uri;
}
@Override
public void apply(org.eclipse.jetty.client.api.Request request)
{
request.header(HttpHeader.PROXY_AUTHORIZATION, value);
}
});
Bug2 is that class BasicAuthentication.BasicResult should be public in order to allow you a simpler way to add authentication results.
--
Simone Bordet
----
http://cometd.org
http://webtide.com
http://intalio.com
Developer advice, training, services and support from the Jetty & CometD experts.
Intalio, the modern way to build business applications.
_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/jetty-users