Issue #408 (Http client does not work on https with proxy)
Fixed by not considering authority-form targets to be URIs, so that the request is correctly copied after a 407.
This commit is contained in:
parent
e6c2c81bea
commit
4039f00bda
|
@ -26,6 +26,7 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.client.api.Authentication;
|
||||
import org.eclipse.jetty.client.api.Connection;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.api.Response;
|
||||
|
@ -171,8 +172,13 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
|||
copyIfAbsent(request, newRequest, HttpHeader.AUTHORIZATION);
|
||||
copyIfAbsent(request, newRequest, HttpHeader.PROXY_AUTHORIZATION);
|
||||
|
||||
newRequest.onResponseSuccess(r -> client.getAuthenticationStore().addAuthenticationResult(authnResult))
|
||||
.send(null);
|
||||
newRequest.onResponseSuccess(r -> client.getAuthenticationStore().addAuthenticationResult(authnResult));
|
||||
|
||||
Connection connection = (Connection)request.getAttributes().get(HttpRequest.CONNECTION_ATTRIBUTE);
|
||||
if (connection != null)
|
||||
connection.send(newRequest, null);
|
||||
else
|
||||
newRequest.send(null);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -105,7 +104,7 @@ public abstract class HttpConnection implements Connection
|
|||
|
||||
URI uri = request.getURI();
|
||||
|
||||
if (proxy != null && !HttpMethod.CONNECT.is(method) && uri != null)
|
||||
if (proxy != null && uri != null)
|
||||
{
|
||||
path = uri.toString();
|
||||
request.path(path);
|
||||
|
|
|
@ -146,6 +146,13 @@ public class HttpProxy extends ProxyConfiguration.Proxy
|
|||
.idleTimeout(2 * connectTimeout, TimeUnit.MILLISECONDS)
|
||||
.timeout(connectTimeout, TimeUnit.MILLISECONDS);
|
||||
|
||||
// In case the proxy replies with a 407, we want
|
||||
// to use the same connection for resending the
|
||||
// request (this time with the Proxy-Authorization
|
||||
// header), so we save it as an attribute to be
|
||||
// used to send the next request.
|
||||
connect.attribute(HttpRequest.CONNECTION_ATTRIBUTE, connection);
|
||||
|
||||
connection.send(connect, result ->
|
||||
{
|
||||
if (result.isFailed())
|
||||
|
|
|
@ -59,6 +59,7 @@ import org.eclipse.jetty.util.Fields;
|
|||
public class HttpRequest implements Request
|
||||
{
|
||||
private static final URI NULL_URI = URI.create("null:0");
|
||||
static final String CONNECTION_ATTRIBUTE = HttpRequest.class.getName() + ".connection";
|
||||
|
||||
private final HttpFields headers = new HttpFields();
|
||||
private final Fields params = new Fields(true);
|
||||
|
@ -171,8 +172,6 @@ public class HttpRequest implements Request
|
|||
else
|
||||
{
|
||||
String rawPath = uri.getRawPath();
|
||||
if (uri.isOpaque())
|
||||
rawPath = path;
|
||||
if (rawPath == null)
|
||||
rawPath = "";
|
||||
this.path = rawPath;
|
||||
|
@ -789,7 +788,7 @@ public class HttpRequest implements Request
|
|||
URI result = newURI(path);
|
||||
if (result == null)
|
||||
return NULL_URI;
|
||||
if (!result.isAbsolute() && !result.isOpaque())
|
||||
if (!result.isAbsolute())
|
||||
result = URI.create(new Origin(getScheme(), getHost(), getPort()).asString() + path);
|
||||
return result;
|
||||
}
|
||||
|
@ -801,7 +800,8 @@ public class HttpRequest implements Request
|
|||
// Handle specially the "OPTIONS *" case, since it is possible to create a URI from "*" (!).
|
||||
if ("*".equals(uri))
|
||||
return null;
|
||||
return new URI(uri);
|
||||
URI result = new URI(uri);
|
||||
return result.isOpaque() ? null : result;
|
||||
}
|
||||
catch (URISyntaxException x)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.proxy;
|
|||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -38,6 +39,7 @@ import org.eclipse.jetty.client.Origin;
|
|||
import org.eclipse.jetty.client.api.Connection;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Destination;
|
||||
import org.eclipse.jetty.client.util.BasicAuthentication;
|
||||
import org.eclipse.jetty.client.util.FutureResponseListener;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
|
@ -449,6 +451,54 @@ public class ForwardProxyTLSServerTest
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyAuthentication() throws Exception
|
||||
{
|
||||
startTLSServer(new ServerHandler());
|
||||
String proxyRealm = "ProxyRealm";
|
||||
startProxy(new ConnectHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
String proxyAuth = request.getHeader(HttpHeader.PROXY_AUTHORIZATION.asString());
|
||||
if (proxyAuth == null)
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.setStatus(HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407);
|
||||
response.setHeader(HttpHeader.PROXY_AUTHENTICATE.asString(), "Basic realm=\"" + proxyRealm + "\"");
|
||||
return;
|
||||
}
|
||||
super.handle(target, baseRequest, request, response);
|
||||
}
|
||||
});
|
||||
|
||||
HttpClient httpClient = new HttpClient(newSslContextFactory());
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
URI proxyURI = URI.create("https://localhost:" + proxyConnector.getLocalPort());
|
||||
httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication(proxyURI, proxyRealm, "proxyUser", "proxyPassword"));
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
{
|
||||
String body = "BODY";
|
||||
ContentResponse response = httpClient.newRequest("localhost", serverConnector.getLocalPort())
|
||||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.method(HttpMethod.GET)
|
||||
.path("/echo")
|
||||
.param("body", body)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
String content = response.getContentAsString();
|
||||
Assert.assertEquals(body, content);
|
||||
}
|
||||
finally
|
||||
{
|
||||
httpClient.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("External Proxy Server no longer stable enough for testing")
|
||||
public void testExternalProxy() throws Exception
|
||||
|
|
Loading…
Reference in New Issue